# HG changeset patch # User Sam # Date 1701530786 -25200 # Node ID 1c3e74f24db0f9b2a0ff08af5bbefec8d02ec76d # Parent 44ec744fbedc59ef83e114fe7d114cd08b4f4882# Parent 611f9cee7495dbca3db6f3a9d4a71fc47d784108 Merge branch 'main' of github.com:saemideluxe/semicongine diff -r 611f9cee7495 -r 1c3e74f24db0 generators/vulkan_api/config.nims --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/generators/vulkan_api/config.nims Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,2 @@ +import strformat + diff -r 611f9cee7495 -r 1c3e74f24db0 generators/vulkan_api/vulkan_api_generator.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/generators/vulkan_api/vulkan_api_generator.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,677 @@ +import std/os +import std/sugar +import std/algorithm +import std/strformat +import std/strutils +import std/sequtils +import std/streams +import std/tables +import httpClient +import std/xmlparser +import std/xmltree + +const + TYPEMAP = { + "void": "void", + "char": "char", + "float": "float32", + "double": "float64", + "int8_t": "int8", + "uint8_t": "uint8", + "int16_t": "int16", + "uint16_t": "uint16", + "int32_t": "int32", + "uint32_t": "uint32", + "uint64_t": "uint64", + "int64_t": "int64", + "size_t": "csize_t", + "int": "cint", + "void*": "pointer", + "char*": "cstring", + "ptr char": "cstring", + "ptr void": "pointer", + "VK_DEFINE_HANDLE": "VkHandle", + "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "VkNonDispatchableHandle", + }.toTable + PLATFORM_HEADER_MAP = { + "X11/Xlib.h": @["xlib", "xlib_xrandr"], + "X11/extensions/Xrandr.h": @["xlib_xrandr"], + "wayland-client.h": @["wayland"], + "windows.h": @["win32"], + "xcb/xcb.h": @["xcb"], + "directfb.h": @["directfb"], + "zircon/types.h": @["fuchsia"], + "ggp_c/vulkan_types.h": @["ggp"], + "screen/screen.h": @["screen"], + "nvscisync.h": @["sci"], + "nvscibuf.h": @["sci"], + "vk_video/vulkan_video_codec_h264std.h": @["provisional"], + "vk_video/vulkan_video_codec_h264std_decode.h": @["provisional"], + "vk_video/vulkan_video_codec_h264std_encode.h": @["provisional"], + "vk_video/vulkan_video_codec_h265std.h": @["provisional"], + "vk_video/vulkan_video_codec_h265std_decode.h": @["provisional"], + "vk_video/vulkan_video_codec_h265std_encode.h": @["provisional"], + }.toTable + MAP_KEYWORD = { + "object": "theobject", + "type": "thetype", + }.toTable + SPECIAL_DEPENDENCIES = { + "VK_NV_ray_tracing": "VK_KHR_ray_tracing_pipeline", + }.toTable + # will be directly loaded at startup + IGNORED_COMMANDS = @["vkGetInstanceProcAddr"] + # can be loaded without a vulkan instance + GLOBAL_COMMANDS = @[ + "vkEnumerateInstanceVersion", + "vkEnumerateInstanceExtensionProperties", + "vkEnumerateInstanceLayerProperties", + "vkCreateInstance", + ] + +# helpers +func mapType(typename: string): auto = + TYPEMAP.getOrDefault(typename.strip(), typename.strip()).strip(chars={'_'}) +func mapName(thename: string): auto = + MAP_KEYWORD.getOrDefault(thename.strip(), thename.strip()).strip(chars={'_'}) +func smartParseInt(value: string): int = + if value.startsWith("0x"): + parseHexInt(value) + else: + parseInt(value) +func hasAttr(node: XmlNode, attr: string): bool = node.attr(attr) != "" +func tableSorted(table: Table[int, string]): seq[(int, string)] = + result = toSeq(table.pairs) + result.sort((a, b) => cmp(a[0], b[0])) +func findType(declNode: XmlNode): string = + # examples: + # char** -> cstringArray + # void* -> pointer + # char* -> cstring + # + # int* -> ptr int + # void** -> ptr pointer + # int** -> ptr ptr int + var basetype = "" + var apointer = "" + var arraylen = "" + for child in declNode: + if child.kind == xnText: + if "[" in child.text: + if "[" in child.text and "]" in child.text: + arraylen = child.text.strip(chars={'[', ']'}).replace("][", "*") + else: + arraylen = declNode.child("enum")[0].text + else: + for i in 0 ..< child.text.count('*'): + apointer = apointer & "ptr " + elif child.tag == "type": + basetype = mapType(child[0].text) + if basetype == "void": + if apointer.count("ptr ") > 0: + basetype = "pointer" + apointer = apointer[0 ..< ^4] + elif basetype == "char": + if apointer.count("ptr ") == 1: + basetype = "cstring" + apointer = "" + elif apointer.count("ptr ") == 2: + basetype = "cstringArray" + apointer = "" + elif apointer.count("ptr ") > 2: + basetype = "cstringArray" + apointer = apointer[0 ..< ^8] + + result = &"{apointer}{basetype}" + if arraylen != "": + result = &"array[{arraylen}, {result}]" + +# serializers +# return values and whether this is a bitfield +func serializeEnum(node: XmlNode, api: XmlNode): (seq[string], string) = + let name = node.attr("name") + if name == "": + return result + + var reservedNames: seq[string] + for t in api.findAll("type"): + reservedNames.add t.attr("name").replace("_", "").toLower() + + # find additional enum defintion in feature definitions + var values: Table[int, string] + for feature in api.findAll("feature"): + for require in feature.findAll("require"): + for theenum in require.findAll("enum"): + if theenum.attr("extends") == name: + if theenum.hasAttr("offset"): + let enumBase = 1000000000 + (smartParseInt(theenum.attr("extnumber")) - 1) * 1000 + var value = smartParseInt(theenum.attr("offset")) + enumBase + if theenum.attr("dir") == "-": + value = -value + values[value] = theenum.attr("name") + elif theenum.hasAttr("value"): + var value = smartParseInt(theenum.attr("value")) + if theenum.attr("dir") == "-": + value = -value + values[value] = theenum.attr("name") + elif theenum.hasAttr("bitpos"): + var value = smartParseInt(theenum.attr("bitpos")) + if theenum.attr("dir") == "-": + value = -value + values[value] = theenum.attr("name") + elif theenum.hasAttr("alias"): + discard + else: + raise newException(Exception, &"Unknown extension value: {feature}\nvalue:{theenum}") + # find additional enum defintion in extension definitions + for extension in api.findAll("extension"): + let extensionNumber = parseInt(extension.attr("number")) + let enumBase = 1000000000 + (extensionNumber - 1) * 1000 + for require in extension.findAll("require"): + for theenum in require.findAll("enum"): + if theenum.attr("extends") == name: + if theenum.hasAttr("offset"): + if theenum.hasAttr("extnumber"): + let otherBase = 1000000000 + (smartParseInt(theenum.attr("extnumber")) - 1) * 1000 + var value = smartParseInt(theenum.attr("offset")) + otherBase + if theenum.attr("dir") == "-": + value = -value + values[value] = theenum.attr("name") + else: + var value = smartParseInt(theenum.attr("offset")) + enumBase + if theenum.attr("dir") == "-": + value = -value + values[value] = theenum.attr("name") + elif theenum.hasAttr("value"): + var value = smartParseInt(theenum.attr("value")) + if theenum.attr("dir") == "-": + value = -value + values[value] = theenum.attr("name") + elif theenum.hasAttr("bitpos"): + var value = smartParseInt(theenum.attr("bitpos")) + if theenum.attr("dir") == "-": + value = -value + values[value] = theenum.attr("name") + elif theenum.hasAttr("alias"): + discard + else: + raise newException(Exception, &"Unknown extension value: {extension}\nvalue:{theenum}") + + # generate enums + if node.attr("type") == "enum": + for value in node.findAll("enum"): + if value.hasAttr("alias"): + continue + if value.attr("value").startsWith("0x"): + values[parseHexInt(value.attr("value"))] = value.attr("name") + else: + values[smartParseInt(value.attr("value"))] = value.attr("name") + if values.len > 0: + result[0].add " " & name & "* {.size: sizeof(cint).} = enum" + for (value, name) in tableSorted(values): + var thename = name + if name.replace("_", "").toLower() in reservedNames: + thename = thename & "_ENUM" + let enumEntry = &" {thename} = {value}" + result[0].add enumEntry + + # generate bitsets (normal enums in the C API, but bitfield-enums in Nim) + elif node.attr("type") == "bitmask": + var predefined_enum_sets: seq[string] + for value in node.findAll("enum"): + if value.hasAttr("bitpos"): + values[smartParseInt(value.attr("bitpos"))] = value.attr("name") + elif node.attr("name") == "VkVideoEncodeRateControlModeFlagBitsKHR": # special exception, for some reason this has values instead of bitpos + values[smartParseInt(value.attr("value"))] = value.attr("name") + elif value.hasAttr("value"): # create a const that has multiple bits set + predefined_enum_sets.add &" {value.attr(\"name\")}* = {value.attr(\"value\")}" + + if values.len > 0: + let cApiName = name.replace("FlagBits", "Flags") + result[1] = cApiName + if node.hasAttr("bitwidth"): + result[0].add " " & name & "* {.size: 8.} = enum" + else: + result[0].add " " & name & "* {.size: sizeof(cint).} = enum" + for (bitpos, enumvalue) in tableSorted(values): + var value = "00000000000000000000000000000000"# makes the bit mask nicely visible + if node.hasAttr("bitwidth"): # assumes this is always 64 + value = value & value + value[^(bitpos + 1)] = '1' + let enumEntry = &" {enumvalue} = 0b{value}" + if not (enumEntry in result[0]): # the specs define duplicate entries for backwards compat + result[0].add enumEntry + if node.hasAttr("bitwidth"): # assuming this attribute is always 64 + if values.len > 0: + result[0].add &"""func toBits*(flags: openArray[{name}]): {cApiName} = + for flag in flags: + result = {cApiName}(uint64(result) or uint64(flag))""" + result[0].add &"""func toEnums*(number: {cApiName}): seq[{name}] = + for value in {name}.items: + if (cast[uint64](value) and uint64(number)) > 0: + result.add value""" + result[0].add &"proc `==`*(a, b: {cApiName}): bool = uint64(a) == uint64(b)" + else: + if values.len > 0: + result[0].add &"""func toBits*(flags: openArray[{name}]): {cApiName} = + for flag in flags: + result = {cApiName}(uint(result) or uint(flag))""" + result[0].add &"""func toEnums*(number: {cApiName}): seq[{name}] = + for value in {name}.items: + if (value.ord and cint(number)) > 0: + result.add value""" + result[0].add &"proc `==`*(a, b: {cApiName}): bool = cint(a) == cint(b)" + if predefined_enum_sets.len > 0: + result[0].add "const" + result[0].add predefined_enum_sets + result[0].add "type" + + +func serializeStruct(node: XmlNode): seq[string] = + let name = node.attr("name") + var union = "" + if node.attr("category") == "union": + union = "{.union.} " + result.add &" {name}* {union}= object" + for member in node.findAll("member"): + if not member.hasAttr("api") or member.attr("api") == "vulkan": + let fieldname = member.child("name")[0].text.strip(chars={'_'}) + result.add &" {mapName(fieldname)}*: {findType(member)}" + +func serializeFunctiontypes(api: XmlNode): seq[string] = + for node in api.findAll("type"): + if node.attr("category") == "funcpointer": + let name = node[1][0] + let returntype = mapType(node[0].text[8 .. ^1].split('(', 1)[0]) + var params: seq[string] + for i in countup(3, node.len - 1, 2): + var paramname = node[i + 1].text.split(',', 1)[0].split(')', 1)[0] + var paramtype = node[i][0].text + if paramname[0] == '*': + paramname = paramname.rsplit(" ", 1)[1] + paramtype = "ptr " & paramtype + paramname = mapName(paramname) + params.add &"{paramname}: {mapType(paramtype)}" + let paramsstr = params.join(", ") + result.add(&" {name}* = proc({paramsstr}): {returntype} {{.cdecl.}}") + +func serializeConsts(api: XmlNode): seq[string] = + result = @["const"] + for enums in api.findAll("enums"): + if enums.attr("name") == "API Constants": + for theenum in enums.findAll("enum"): + if theenum.hasAttr("alias"): + result.add &" {theenum.attr(\"name\")}* = {theenum.attr(\"alias\")}" + else: + var value = theenum.attr("value").strip(chars={'(', ')'}) + if value.endsWith("U"): + value = value[0..^2] & "'u32" + elif value.endsWith("ULL"): + value = value[0..^4] & "'u64" + if value[0] == '~': + value = "not " & value[1..^1] + result.add &" {theenum.attr(\"name\")}*: {mapType(theenum.attr(\"type\"))} = {value}" + +func serializeType(node: XmlNode, headerTypes: Table[string, string]): Table[string, seq[string]] = + if node.attrsLen == 0: + return + if node.attr("requires") == "vk_platform" or node.attr("category") == "include": + return + result["basetypes"] = @[] + result["enums"] = @[] + + # include-defined types (in platform headers) + if node.attr("name") in headerTypes: + for platform in PLATFORM_HEADER_MAP[node.attr("requires")]: + let platformfile = "platform/" & platform + if not result.hasKey(platformfile): + result[platformfile] = @[] + result[platformfile].add " " & node.attr("name").strip(chars={'_'}) & " *{.header: \"" & node.attr("requires") & "\".} = object" + # generic base types + elif node.attr("category") == "basetype": + let typechild = node.child("type") + let namechild = node.child("name") + if typechild != nil and namechild != nil: + var typename = typechild[0].text + if node[2].kind == xnText and node[2].text.strip() == "*": + typename = &"ptr {typename}" + result["basetypes"].add &" {namechild[0].text}* = {mapType(typename)}" + elif namechild != nil: + result["basetypes"].add &" {namechild[0].text}* = object" + # function pointers need to be handled with structs + elif node.attr("category") == "funcpointer": + discard + # preprocessor defines, ignored + elif node.attr("category") == "define": + discard + # bitmask aliases + elif node.attr("category") == "bitmask": + if node.hasAttr("alias"): + let name = node.attr("name") + let alias = node.attr("alias") + result["enums"].add &" {name}* = {alias}" + # distinct resource ID types aka handles + elif node.attr("category") == "handle": + if not node.hasAttr("alias"): + let name = node.child("name")[0].text + var thetype = mapType(node.child("type")[0].text) + result["basetypes"].add &" {name}* = distinct {thetype}" + # enum aliases + elif node.attr("category") == "enum": + if node.hasAttr("alias"): + let name = node.attr("name") + let alias = node.attr("alias") + result["enums"].add &" {name}* = {alias}" + else: + discard + +func serializeCommand(node: XmlNode): (string, string) = + let + proto = node.child("proto") + resulttype = mapType(proto.child("type")[0].text) + name = proto.child("name")[0].text + var params: seq[string] + for param in node: + if param.tag == "param" and param.attr("api") in ["", "vulkan"]: + let fieldname = param.child("name")[0].text.strip(chars={'_'}) + params.add &"{mapName(fieldname)}: {findType(param)}" + let allparams = params.join(", ") + return (name, &"proc({allparams}): {resulttype} {{.stdcall.}}") + + +proc update(a: var Table[string, seq[string]], b: Table[string, seq[string]]) = + for k, v in b.pairs: + if not a.hasKey(k): + a[k] = @[] + a[k].add v + + +proc main() = + let file = getTempDir() / "vk.xml" + if not os.fileExists(file): + let client = newHttpClient() + let glUrl = "https://raw.githubusercontent.com/KhronosGroup/Vulkan-Docs/main/xml/vk.xml" + client.downloadFile(glUrl, file) + + let api = loadXml(file) + + const outdir = "src/vulkan_api/output" + removeDir outdir + createDir outdir + createDir outdir / "platform" + + # index all names that are only available on certain platforms + var platformTypes: Table[string, string] + for extension in api.findAll("extension"): + if extension.hasAttr("platform"): + for thetype in extension.findAll("type"): + platformTypes[thetype.attr("name")] = extension.attr("platform") + for command in extension.findAll("command"): + platformTypes[command.attr("name")] = extension.attr("platform") + elif extension.attr("name").startsWith("VK_KHR_video"): + for thetype in extension.findAll("type"): + platformTypes[thetype.attr("name")] = "provisional" + for command in extension.findAll("command"): + platformTypes[command.attr("name")] = "provisional" + + var outputFiles = { + "basetypes": @[ + "import std/dynlib", + "import std/tables", + "import std/strutils", + "import std/logging", + "import std/typetraits", + "import std/macros", + "type", + " VkHandle* = distinct uint", + " VkNonDispatchableHandle* = distinct uint", + "when defined(linux):", + " let vulkanLib* = loadLib(\"libvulkan.so.1\")", + "when defined(windows):", + " let vulkanLib* = loadLib(\"vulkan-1.dll\")", + "if vulkanLib == nil:", + " raise newException(Exception, \"Unable to load vulkan library\")", + "func VK_MAKE_API_VERSION*(variant: uint32, major: uint32, minor: uint32, patch: uint32): uint32 {.compileTime.} =", + " (variant shl 29) or (major shl 22) or (minor shl 12) or patch", + "", + """template checkVkResult*(call: untyped) = + when defined(release): + discard call + else: + # yes, a bit cheap, but this is only for nice debug output + var callstr = astToStr(call).replace("\n", "") + while callstr.find(" ") >= 0: + callstr = callstr.replace(" ", " ") + debug "CALLING vulkan: ", callstr + let value = call + if value != VK_SUCCESS: + error "Vulkan error: ", astToStr(call), " returned ", $value + raise newException(Exception, "Vulkan error: " & astToStr(call) & + " returned " & $value)""", + """ +# custom enum iteration (for enum values > 2^16) +macro enumFullRange(a: typed): untyped = + newNimNode(nnkBracket).add(a.getType[1][1..^1]) + +iterator items*[T: HoleyEnum](E: typedesc[T]): T = + for a in enumFullRange(E): yield a""", + ], + "structs": @["type"], + "enums": @["type"], + "commands": @[], + }.toTable + outputFiles["basetypes"].add serializeConsts(api) + outputFiles["basetypes"].add "type" + + # enums + for thetype in api.findAll("type"): + if thetype.attr("category") == "bitmask" and not thetype.hasAttr("alias") and (not thetype.hasAttr("api") or thetype.attr("api") == "vulkan"): + let name = thetype.child("name")[0].text + outputFiles["enums"].add &" {name}* = distinct VkFlags" + + var bitfields: Table[string, string] + outputFiles["enums"].add "let vkGetInstanceProcAddr = cast[proc(instance: VkInstance, name: cstring): pointer {.stdcall.}](checkedSymAddr(vulkanLib, \"vkGetInstanceProcAddr\"))" + outputFiles["enums"].add "type" + for theenum in api.findAll("enums"): + let (enums, bitFieldName) = serializeEnum(theenum, api) + outputFiles["enums"].add enums + if bitFieldName != "": + bitfields[theenum.attr("name")] = bitFieldName + + # bitmask-to-string functions + for thetype in api.findAll("type"): + if thetype.attr("name") in bitfields: + let name = bitfields[thetype.attr("name")] + let stringfunc = &"proc `$`*(bitset: {name}): string = $toEnums(bitset)" + if not (stringfunc in outputFiles["enums"]): + outputFiles["enums"].add stringfunc + outputFiles["enums"].add "type" + + # structs and function types need to be in same "type" block to avoid forward-declarations + outputFiles["structs"].add serializeFunctiontypes(api) + for thetype in api.findAll("type"): + if thetype.attr("category") == "struct" or thetype.attr("category") == "union": + var outfile = "structs" + if thetype.attr("name") in platformTypes: + outfile = "platform/" & platformTypes[thetype.attr("name")] + if not (outfile in outputFiles): + outputFiles[outfile] = @[] + outputFiles[outfile].add serializeStruct(thetype) + + # types + var headerTypes: Table[string, string] + for types in api.findAll("types"): + for thetype in types.findAll("type"): + if thetype.attrsLen == 2 and thetype.hasAttr("requires") and thetype.hasAttr("name") and thetype.attr("requires") != "vk_platform": + let name = thetype.attr("name") + let incld = thetype.attr("requires") + headerTypes[name] = &"{name} {{.header: \"{incld}\".}} = object" + + for typesgroup in api.findAll("types"): + for thetype in typesgroup.findAll("type"): + outputFiles.update serializeType(thetype, headerTypes) + + for typesgroup in api.findAll("types"): + for node in typesgroup.findAll("type"): + if node.attr("category") == "handle": + if not node.hasAttr("alias"): + let name = node.child("name")[0].text + outputFiles["basetypes"].add &"proc `$`*(handle: {name}): string = \"{name}(\" & $(uint(handle)) & \")\"" + outputFiles["basetypes"].add &"proc valid*(handle: {name}): bool = uint(handle) != 0" + outputFiles["basetypes"].add &"proc reset*(handle: var {name}) = handle = {name}(0)" + outputFiles["basetypes"].add &"proc `==`*(a, b: {name}): bool = uint(a) == uint(b)" + + + # commands aka functions + var varDecls: Table[string, string] + var procLoads: Table[string, string] # procloads need to be packed into feature/extension loader procs + for commands in api.findAll("commands"): + for command in commands.findAll("command"): + if command.attr("api") != "vulkansc" and not (command.attr("name") in IGNORED_COMMANDS): + if command.hasAttr("alias"): + let name = command.attr("name") + let alias = command.attr("alias") + let thetype = varDecls[alias].split(":", 1)[1].strip() + varDecls[name] = &" {name}*: {thetype}" + procLoads[name] = &" {name} = {alias}" + else: + let (name, thetype) = serializeCommand(command) + varDecls[name] = &" {name}*: {thetype}" + procLoads[name] = &" {name} = cast[{thetype}](vkGetInstanceProcAddr(instance, \"{name}\"))" + var declared: seq[string] + var featureloads: seq[string] + for feature in api.findAll("feature"): + if feature.attr("api") in ["vulkan", "vulkan,vulkansc"]: + let name = feature.attr("name") + outputFiles["commands"].add &"# feature {name}" + outputFiles["commands"].add "var" + for command in feature.findAll("command"): + if not (command.attr("name") in declared) and not (command.attr("name") in IGNORED_COMMANDS): + outputFiles["commands"].add varDecls[command.attr("name")] + declared.add command.attr("name") + featureloads.add &"load{name}" + outputFiles["commands"].add &"proc load{name}*(instance: VkInstance) =" + for command in feature.findAll("command"): + if not (command.attr("name") in IGNORED_COMMANDS & GLOBAL_COMMANDS): + outputFiles["commands"].add procLoads[command.attr("name")] + outputFiles["commands"].add "" + outputFiles["commands"].add ["proc loadVulkan*(instance: VkInstance) ="] + for l in featureloads: + outputFiles["commands"].add [&" {l}(instance)"] + outputFiles["commands"].add "" + + # for promoted extensions, dependants need to call the load-function of the promoted feature/extension + # use table to store promotions + var promotions: Table[string, string] + for extensions in api.findAll("extensions"): + for extension in extensions.findAll("extension"): + if extension.hasAttr("promotedto"): + promotions[extension.attr("name")] = extension.attr("promotedto") + + var extensionDependencies: Table[string, (seq[string], XmlNode)] + var features: seq[string] + for feature in api.findAll("feature"): + features.add feature.attr("name") + for extensions in api.findAll("extensions"): + for extension in extensions.findAll("extension"): + let name = extension.attr("name") + extensionDependencies[name] = (@[], extension) + if extension.hasAttr("depends"): + extensionDependencies[name] = (extension.attr("depends").split("+"), extension) + if extension.attr("depends").startsWith("("): # no need for full tree parser, only single place where we can use a feature + let dependencies = extension.attr("depends").rsplit({')'}, 1)[1][1 .. ^1].split("+") + extensionDependencies[name] = (dependencies, extension) + if name in SPECIAL_DEPENDENCIES: + extensionDependencies[name][0].add SPECIAL_DEPENDENCIES[name] + + # order dependencies to generate them in correct order + var dependencyOrderedExtensions: OrderedTable[string, XmlNode] + while extensionDependencies.len > 0: + var delkeys: seq[string] + for extensionName, (dependencies, extension) in extensionDependencies.pairs: + var missingExtension = false + for dep in dependencies: + let realdep = promotions.getOrDefault(dep, dep) + if not (realdep in dependencyOrderedExtensions) and not (realdep in features): + missingExtension = true + break + if not missingExtension: + dependencyOrderedExtensions[extensionName] = extension + delkeys.add extensionName + for key in delkeys: + extensionDependencies.del key + + var extensionLoaderMap: Table[string, Table[string, string]] + for extension in dependencyOrderedExtensions.values: + if extension.hasAttr("promotedto"): # will be loaded in promoted place + continue + if extension.attr("supported") in ["", "vulkan", "vulkan,vulkansc"]: + var file = "commands" + var platform = extension.attr("platform") + if extension.attr("name").startsWith("VK_KHR_video"): + platform = "provisional" + if platform != "": + file = "platform/" & platform + let name = extension.attr("name") + if extension.findAll("command").len > 0: + outputFiles[file].add &"# extension {name}" + outputFiles[file].add "var" + for command in extension.findAll("command"): + if not (command.attr("name") in declared) and not (command.attr("name") in IGNORED_COMMANDS): + outputFiles[file].add varDecls[command.attr("name")] + declared.add command.attr("name") + outputFiles[file].add &"proc load{name}*(instance: VkInstance) =" + if not (platform in extensionLoaderMap): + extensionLoaderMap[platform] = Table[string, string]() + extensionLoaderMap[platform][name] = &"load{name}" + var addedFunctionBody = false + if extension.hasAttr("depends"): + for dependency in extension.attr("depends").split("+"): + # need to check since some extensions have no commands and therefore no load-function + outputFiles[file].add &" load{promotions.getOrDefault(dependency, dependency)}(instance)" + addedFunctionBody = true + for command in extension.findAll("command"): + outputFiles[file].add procLoads[command.attr("name")] + addedFunctionBody = true + if not addedFunctionBody: + outputFiles[file].add " discard" + outputFiles[file].add "" + + var mainout: seq[string] + for section in ["basetypes", "enums", "structs", "commands"]: + mainout.add outputFiles[section] + mainout.add "var EXTENSION_LOADERS = {" + for extension, loader in extensionLoaderMap[""].pairs: + mainout.add &" \"{extension}\": {loader}," + mainout.add "}.toTable" + for platform in api.findAll("platform"): + mainout.add &"when defined({platform.attr(\"protect\")}):" + mainout.add &" ../vulkan/include platform/{platform.attr(\"name\")}" + if platform.attr("name") in extensionLoaderMap: + for extension, loader in extensionLoaderMap[platform.attr("name")].pairs: + mainout.add &" EXTENSION_LOADERS[\"{extension}\"] = {loader}" + + mainout.add "" + mainout.add "proc loadExtension*(instance: VkInstance, extension: string) = EXTENSION_LOADERS[extension](instance)" + mainout.add "" + mainout.add "# load global functions immediately" + mainout.add "block globalFunctions:" + mainout.add " let instance = VkInstance(0)" + for l in GLOBAL_COMMANDS: + mainout.add procLoads[l] + mainout.add "" + # produces error if enable both implicit converters + # mainout.add "converter VkBool2NimBool*(a: VkBool32): bool = a > 0" + mainout.add "converter NimBool2VkBool*(a: bool): VkBool32 = VkBool32(a)" + + writeFile outdir / &"api.nim", mainout.join("\n") + + + for filename, filecontent in outputFiles.pairs: + if filename.startsWith("platform/"): + writeFile outdir / &"{filename}.nim", (@[ + "type" + ] & filecontent).join("\n") + +when isMainModule: + main() diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,37 @@ +import std/tables +export tables # necessary to use some features without weird compilation error + +import semicongine/core +export core + +import semicongine/audio +import semicongine/animation +import semicongine/engine +import semicongine/collision +import semicongine/scene +import semicongine/events +import semicongine/material +import semicongine/mesh +import semicongine/noise +import semicongine/renderer +import semicongine/resources +import semicongine/settings +import semicongine/text +import semicongine/platform/window +import semicongine/vulkan + +export audio +export animation +export engine +export collision +export scene +export events +export material +export mesh +export noise +export renderer +export resources +export settings +export text +export window +export vulkan diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/animation.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/animation.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,171 @@ +import std/sugar +import std/tables +import std/math +import std/sequtils +import std/algorithm + +import ./core/matrix + +type + Ease* = enum + None + Linear + Pow2 + Pow3 + Pow4 + Pow5 + Expo + Sine + Circ + AnimationTime* = 0'f32 .. 1'f32 + Direction* = enum + Forward + Backward + Alternate + Keyframe[T] = object + timestamp: AnimationTime + value : T + easeIn: Ease + easeOut: Ease + Animation*[T] = object + animationFunction: (t: AnimationTime) -> T + duration: float32 + direction: Direction + iterations: int + AnimationPlayer*[T] = object + animation*: Animation[T] + currentTime*: float32 + playing*: bool + currentDirection: int + currentIteration: int + currentValue*: T + +func easeConst(x: float32): float32 = 0 +func easeLinear(x: float32): float32 = x +func easePow2(x: float32): float32 = x * x +func easePow3(x: float32): float32 = x * x * x +func easePow4(x: float32): float32 = x * x * x * x +func easePow5(x: float32): float32 = x * x * x * x * x +func easeExpo(x: float32): float32 = ( if x == 0: 0'f32 else: pow(2'f32, 10'f32 * x - 10'f32) ) +func easeSine(x: float32): float32 = 1'f32 - cos((x * PI) / 2'f32) +func easeCirc(x: float32): float32 = 1'f32 - sqrt(1'f32 - pow(x, 2'f32)) + +const EASEFUNC_MAP = { + None: easeConst, + Linear: easeLinear, + Pow2: easePow2, + Pow3: easePow3, + Pow4: easePow4, + Pow5: easePow5, + Expo: easeExpo, + Sine: easeSine, + Circ: easeCirc, +}.toTable() + +func makeEaseOut(f: proc(x: float32): float32 {.noSideEffect.}): auto = + func wrapper(x: float32): float32 = + 1 - f(1 - x) + return wrapper + +func combine(f1: proc(x: float32): float32 {.noSideEffect.}, f2: proc(x: float32): float32 {.noSideEffect.}): auto = + func wrapper(x: float32): float32 = + if x < 0.5: f1(x * 2) * 0.5 + else: f2((x - 0.5) * 2) * 0.5 + 0.5 + return wrapper + +func interpol(keyframe: Keyframe, t: float32): float32 = + if keyframe.easeOut == None: + return EASEFUNC_MAP[keyframe.easeIn](t) + elif keyframe.easeIn == None: + return EASEFUNC_MAP[keyframe.easeOut](t) + else: + return combine(EASEFUNC_MAP[keyframe.easeIn], makeEaseOut(EASEFUNC_MAP[keyframe.easeOut]))(t) + +func keyframe*[T](timestamp: AnimationTime, value: T, easeIn=Linear, easeOut=None): Keyframe[T] = + Keyframe[T](timestamp: timestamp, value: value, easeIn: easeIn, easeOut: easeOut) + +func newAnimation*[T](keyframes: openArray[Keyframe[T]], duration: float32, direction=Forward, iterations=1): Animation[T] = + assert keyframes.len >= 2, "An animation needs at least 2 keyframes" + assert keyframes[0].timestamp == 0, "An animation's first keyframe needs to have timestamp=0" + assert keyframes[^1].timestamp == 1, "An animation's last keyframe needs to have timestamp=1" + var last = keyframes[0].timestamp + for kf in keyframes[1 .. ^1]: + assert kf.timestamp > last, "Succeding keyframes must have increasing timestamps" + last = kf.timestamp + + let theKeyframes = keyframes.toSeq + + proc animationFunc(t: AnimationTime): T = + var i = 0 + while i < theKeyframes.len - 1: + if theKeyframes[i].timestamp > t: + break + inc i + + let + keyFrameDist = theKeyframes[i].timestamp - theKeyframes[i - 1].timestamp + timestampDist = t - theKeyframes[i - 1].timestamp + x = timestampDist / keyFrameDist + + let value = theKeyframes[i - 1].interpol(x) + return theKeyframes[i].value * value + theKeyframes[i - 1].value * (1 - value) + + Animation[T]( + animationFunction: animationFunc, + duration: duration, + direction: direction, + iterations: iterations + ) + +func newAnimation*[T](fun: (t: AnimationTime) -> T, duration: float32, direction=Forward, iterations=1): Animation[T] = + Animation[T]( + animationFunction: fun, + duration: duration, + direction: direction, + iterations: iterations + ) + +proc reset*(player: var AnimationPlayer) = + player.currentValue = player.animation.animationFunction(0) + player.currentTime = 0 + player.currentDirection = if player.animation.direction == Backward: -1 else : 1 + player.currentIteration = player.animation.iterations + + +proc newAnimationPlayer*[T](animation: Animation[T]): AnimationPlayer[T] = + result = AnimationPlayer[T](animation: animation, playing: false) + result.reset() + +proc newAnimationPlayer*[T](value: T = default(T)): AnimationPlayer[T] = + newAnimationPlayer[T](newAnimation[T]((t: AnimationTime) => value, 0)) + +func start*(player: var AnimationPlayer) = + player.playing = true + +func stop*(player: var AnimationPlayer) = + player.playing = false + +proc advance*[T](player: var AnimationPlayer[T], dt: float32): T = + # TODO: check this function, not 100% correct I think + if player.playing: + player.currentTime += float32(player.currentDirection) * dt + if not (0 <= player.currentTime and player.currentTime < player.animation.duration): + dec player.currentIteration + # last iteration reached + if player.currentIteration <= 0 and player.animation.iterations != 0: + player.stop() + # more iterations + else: + case player.animation.direction: + of Forward: + player.currentTime = player.currentTime - player.animation.duration + of Backward: + player.currentTime = player.currentTime + player.animation.duration + of Alternate: + player.currentDirection = -player.currentDirection + player.currentTime += float32(player.currentDirection) * dt * 2'f32 + + player.currentValue = player.animation.animationFunction( + max(low(AnimationTime), min(player.currentTime / player.animation.duration, high(AnimationTime))) + ) + return player.currentValue diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/audio.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/audio.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,211 @@ +import std/tables +import std/locks +import std/logging except Level + +when defined(windows): # used for setting audio thread priority + import winim +when defined(linux): + import std/posix + +import ./core +import ./platform/audio +import ./resources + +export audiotypes + +const NBUFFERS = 4 +const BUFFERSAMPLECOUNT = 2048 + +type + Playback = object + sound: Sound + position: int + loop: bool + levelLeft: Level + levelRight: Level + Track = object + playing: Table[uint64, Playback] + level: Level + Mixer* = object + playbackCounter: uint64 + tracks: Table[string, Track] + sounds*: Table[string, Sound] + level: Level + device: NativeSoundDevice + lock: Lock + buffers: seq[SoundData] + currentBuffer: int + +proc initMixer*(): Mixer = + result = Mixer( + tracks: {"": Track(level: 1'f)}.toTable, + level: 1'f, + ) + result.lock.initLock() + +proc setupDevice(mixer: var Mixer) = + # call this inside audio thread + var bufferaddresses: seq[ptr SoundData] + for i in 0 ..< NBUFFERS: + mixer.buffers.add newSeq[Sample](BUFFERSAMPLECOUNT) + for i in 0 ..< mixer.buffers.len: + bufferaddresses.add (addr mixer.buffers[i]) + mixer.device = openSoundDevice(AUDIO_SAMPLE_RATE, bufferaddresses) + +proc loadSound*(mixer: var Mixer, name: string, resource: string) = + assert not (name in mixer.sounds) + mixer.sounds[name] = loadAudio(resource) + +proc addSound*(mixer: var Mixer, name: string, sound: Sound) = + assert not (name in mixer.sounds) + mixer.sounds[name] = sound + +proc replaceSound*(mixer: var Mixer, name: string, sound: Sound) = + assert (name in mixer.sounds) + mixer.sounds[name] = sound + +proc addTrack*(mixer: var Mixer, name: string, level: Level=1'f) = + assert not (name in mixer.tracks) + mixer.lock.withLock(): + mixer.tracks[name] = Track(level: level) + +proc play*(mixer: var Mixer, soundName: string, track="", stopOtherSounds=false, loop=false, levelLeft, levelRight: Level): uint64 = + assert track in mixer.tracks + assert soundName in mixer.sounds, soundName & " not loaded" + mixer.lock.withLock(): + if stopOtherSounds: + mixer.tracks[track].playing.clear() + mixer.tracks[track].playing[mixer.playbackCounter] = Playback( + sound: mixer.sounds[soundName], + position: 0, + loop: loop, + levelLeft: levelLeft, + levelRight: levelRight + ) + result = mixer.playbackCounter + inc mixer.playbackCounter + +proc play*(mixer: var Mixer, soundName: string, track="", stopOtherSounds=false, loop=false, level: Level=1'f): uint64 = + play( + mixer=mixer, + soundName=soundName, + track=track, + stopOtherSounds=stopOtherSounds, + loop=loop, + levelLeft=level, + levelRight=level + ) + +proc stop*(mixer: var Mixer) = + mixer.lock.withLock(): + for track in mixer.tracks.mvalues: + track.playing.clear() + +proc getLevel*(mixer: var Mixer): Level = mixer.level +proc getLevel*(mixer: var Mixer, track: string): Level = mixer.tracks[track].level +proc getLevel*(mixer: var Mixer, playbackId : uint64): (Level, Level) = + for track in mixer.tracks.mvalues: + if playbackId in track.playing: + return (track.playing[playbackId].levelLeft, track.playing[playbackId].levelRight) + +proc setLevel*(mixer: var Mixer, level: Level) = mixer.level = level +proc setLevel*(mixer: var Mixer, track: string, level: Level) = + mixer.lock.withLock(): + mixer.tracks[track].level = level +proc setLevel*(mixer: var Mixer, playbackId: uint64, levelLeft, levelRight: Level) = + mixer.lock.withLock(): + for track in mixer.tracks.mvalues: + if playbackId in track.playing: + track.playing[playbackId].levelLeft = levelLeft + track.playing[playbackId].levelRight = levelRight +proc setLevel*(mixer: var Mixer, playbackId : uint64, level: Level) = + setLevel(mixer, playbackId, level, level) + +proc stop*(mixer: var Mixer, track: string) = + assert track in mixer.tracks + mixer.lock.withLock(): + mixer.tracks[track].playing.clear() + +proc stop*(mixer: var Mixer, playbackId: uint64) = + mixer.lock.withLock(): + for track in mixer.tracks.mvalues: + if playbackId in track.playing: + track.playing.del(playbackId) + break + +proc isPlaying*(mixer: var Mixer): bool = + mixer.lock.withLock(): + for track in mixer.tracks.mvalues: + if track.playing.len > 0: + return true + return false + +proc isPlaying*(mixer: var Mixer, track: string): bool = + mixer.lock.withLock(): + return mixer.tracks.contains(track) and mixer.tracks[track].playing.len > 0 + +func applyLevel(sample: Sample, levelLeft, levelRight: Level): Sample = + [int16(float(sample[0]) * levelLeft), int16(float(sample[1]) * levelRight)] + +func clip(value: int32): int16 = + int16(max(min(int32(high(int16)), value), int32(low(int16)))) + +# used for combining sounds +func mix(a, b: Sample): Sample = + [ + clip(int32(a[0]) + int32(b[0])), + clip(int32(a[1]) + int32(b[1])), + ] + +proc updateSoundBuffer(mixer: var Mixer) = + # mix + for i in 0 ..< mixer.buffers[mixer.currentBuffer].len: + var currentSample = [0'i16, 0'i16] + mixer.lock.withLock(): + for track in mixer.tracks.mvalues: + var stoppedSounds: seq[uint64] + for (id, playback) in track.playing.mpairs: + let sample = applyLevel( + playback.sound[][playback.position], + mixer.level * track.level * playback.levelLeft, + mixer.level * track.level * playback.levelRight, + ) + currentSample = mix(currentSample, sample) + inc playback.position + if playback.position >= playback.sound[].len: + if playback.loop: + playback.position = 0 + else: + stoppedSounds.add id + for id in stoppedSounds: + track.playing.del(id) + mixer.buffers[mixer.currentBuffer][i] = currentSample + # send data to sound device + mixer.device.writeSoundData(mixer.currentBuffer) + mixer.currentBuffer = (mixer.currentBuffer + 1) mod mixer.buffers.len + + +proc destroy*(mixer: var Mixer) = + mixer.lock.deinitLock() + mixer.device.closeSoundDevice() + +# Threaded implementation, usually used for audio + +var + mixer* = createShared(Mixer) + audiothread: Thread[void] + +proc audioWorker() {.thread.} = + mixer[].setupDevice() + onThreadDestruction(proc() = mixer[].lock.withLock(mixer[].destroy()); freeShared(mixer)) + while true: + mixer[].updateSoundBuffer() + +proc startMixerThread*() = + mixer[] = initMixer() + audiothread.createThread(audioWorker) + debug "Created audio thread" + when defined(window): + SetThreadPriority(audiothread.handle(), THREAD_PRIORITY_TIME_CRITICAL) + when defined(linux): + discard pthread_setschedprio(Pthread(audiothread.handle()), cint(-20)) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/collision.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/collision.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,386 @@ +import ./core + +const MAX_COLLISON_DETECTION_ITERATIONS = 20 +const MAX_COLLISON_POINT_CALCULATION_ITERATIONS = 20 + +type + ColliderType* = enum + Box, Sphere, Points + Collider* = object + transform*: Mat4 = Unit4F32 + case theType*: ColliderType + of Box: discard + of Sphere: radius*: float32 + of Points: points*: seq[Vec3f] + +func between(value, b1, b2: float32): bool = + min(b1, b2) <= value and value <= max(b1, b2) + +func contains*(collider: Collider, x: Vec3f): bool = + # from https://math.stackexchange.com/questions/1472049/check-if-a-point-is-inside-a-rectangular-shaped-area-3d + case collider.theType: + of Box: + let + P1 = collider.transform * newVec3f(0, 0, 0) # origin + P2 = collider.transform * Z + P4 = collider.transform * X + P5 = collider.transform * Y + u = (P1 - P4).cross(P1 - P5) + v = (P1 - P2).cross(P1 - P5) + w = (P1 - P2).cross(P1 - P4) + uP1 = u.dot(P1) + uP2 = u.dot(P2) + vP1 = v.dot(P1) + vP4 = v.dot(P4) + wP1 = w.dot(P1) + wP5 = w.dot(P5) + ux = u.dot(x) + vx = v.dot(x) + wx = w.dot(x) + ux.between(uP1, uP2) and vx.between(vP1, vP4) and wx.between(wP1, wP5) + of Sphere: + (collider.transform * x).length < (collider.transform * newVec3f()).length + of Points: + raise newException(Exception, "Points are not supported yet for 'contains'") + +# implementation of GJK, based on https://blog.winter.dev/2020/gjk-algorithm/ + +# most generic implementation of findFurthestPoint +# add other implementations of findFurthestPoint for other kind of geometry or optimization +# (will be selected depening on type of the first parameter) +func findFurthestPoint(points: openArray[Vec3f], direction: Vec3f): Vec3f = + var maxDist = low(float32) + for p in points: + let dist = direction.dot(p) + if dist > maxDist: + maxDist = dist + result = p + +func findFurthestPoint(transform: Mat4, direction: Vec3f): Vec3f = + return findFurthestPoint( + [ + transform * newVec3f(0, 0, 0), + transform * X, + transform * Y, + transform * Z, + transform * (X + Y), + transform * (X + Z), + transform * (Y + Z), + transform * (X + Y + Z), + ], + direction + ) +func findFurthestPoint(collider: Collider, direction: Vec3f): Vec3f = + case collider.theType + of Sphere: + let directionNormalizedToSphere = ((direction / direction.length) * collider.radius) + collider.transform * directionNormalizedToSphere + of Box: + findFurthestPoint(collider.transform, direction) + of Points: + findFurthestPoint(collider.points, direction) + +func supportPoint(a, b: Collider, direction: Vec3f): Vec3f = + a.findFurthestPoint(direction) - b.findFurthestPoint(-direction) + +func sameDirection(direction: Vec3f, ao: Vec3f): bool = + direction.dot(ao) > 0 + +func line(simplex: var seq[Vec3f], direction: var Vec3f): bool = + let + a = simplex[0] + b = simplex[1] + ab = b - a + ao = - a + + if sameDirection(ab, ao): + direction = cross(cross(ab, ao), ab) + else: + simplex = @[a] + direction = ao + + return false + +func triangle(simplex: var seq[Vec3f], direction: var Vec3f, twoDimensional=false): bool = + let + a = simplex[0] + b = simplex[1] + c = simplex[2] + ab = b - a + ac = c - a + ao = - a + abc = ab.cross(ac) + + if sameDirection(abc.cross(ac), ao): + if sameDirection(ac, ao): + simplex = @[a, c] + direction = ac.cross(ao).cross(ac) + else: + simplex = @[a, b] + return line(simplex, direction) + else: + if (sameDirection(ab.cross(abc), ao)): + simplex = @[a, b] + return line(simplex, direction) + else: + if twoDimensional: + return true + if (sameDirection(abc, ao)): + direction = abc + else: + simplex = @[ a, c, b] + direction = -abc + + return false + +func tetrahedron(simplex: var seq[Vec3f], direction: var Vec3f): bool = + let + a = simplex[0] + b = simplex[1] + c = simplex[2] + d = simplex[3] + ab = b - a + ac = c - a + ad = d - a + ao = - a + abc = ab.cross(ac) + acd = ac.cross(ad) + adb = ad.cross(ab) + + if sameDirection(abc, ao): + simplex = @[a, b, c] + return triangle(simplex, direction) + if sameDirection(acd, ao): + simplex = @[a, c, d] + return triangle(simplex, direction) + if sameDirection(adb, ao): + simplex = @[a, d, b] + return triangle(simplex, direction) + + return true + +func getFaceNormals(polytope: seq[Vec3f], faces: seq[int]): (seq[Vec4f], int) = + var + normals: seq[Vec4f] + minTriangle = 0 + minDistance = high(float32) + + for i in countup(0, faces.len - 1, 3): + let + a = polytope[faces[i + 0]] + b = polytope[faces[i + 1]] + c = polytope[faces[i + 2]] + + var normal = (b - a).cross(c - a).normalized() + var distance = normal.dot(a) + + if distance < 0: + normal = normal * -1'f32 + distance = distance * -1'f32 + + normals.add normal.toVec4(distance) + + if distance < minDistance: + minTriangle = i div 3 + minDistance = distance + + return (normals, minTriangle) + +func addIfUniqueEdge(edges: var seq[(int, int)], faces: seq[int], a: int, b: int) = + let reverse = edges.find((faces[b], faces[a])) + if (reverse >= 0): + edges.delete(reverse) + else: + edges.add (faces[a], faces[b]) + +func nextSimplex(simplex: var seq[Vec3f], direction: var Vec3f, twoDimensional=false): bool = + case simplex.len + of 2: simplex.line(direction) + of 3: simplex.triangle(direction, twoDimensional) + of 4: simplex.tetrahedron(direction) + else: raise newException(Exception, "Error in simplex") + +func collisionPoint3D(simplex: var seq[Vec3f], a, b: Collider): tuple[normal: Vec3f, penetrationDepth: float32] = + var + polytope = simplex + faces = @[ + 0, 1, 2, + 0, 3, 1, + 0, 2, 3, + 1, 3, 2 + ] + (normals, minFace) = getFaceNormals(polytope, faces) + minNormal: Vec3f + minDistance = high(float32) + iterCount = 0 + + while minDistance == high(float32) and iterCount < MAX_COLLISON_POINT_CALCULATION_ITERATIONS: + minNormal = normals[minFace].xyz + minDistance = normals[minFace].w + var + support = supportPoint(a, b, minNormal) + sDistance = minNormal.dot(support) + + if abs(sDistance - minDistance) > 0.001'f32: + minDistance = high(float32) + var uniqueEdges: seq[(int, int)] + var i = 0 + while i < normals.len: + if sameDirection(normals[i], support): + var f = i * 3 + + addIfUniqueEdge(uniqueEdges, faces, f + 0, f + 1) + addIfUniqueEdge(uniqueEdges, faces, f + 1, f + 2) + addIfUniqueEdge(uniqueEdges, faces, f + 2, f + 0) + + faces[f + 2] = faces.pop() + faces[f + 1] = faces.pop() + faces[f + 0] = faces.pop() + + normals[i] = normals.pop() + + dec i + inc i + + var newFaces: seq[int] + for (edgeIndex1, edgeIndex2) in uniqueEdges: + newFaces.add edgeIndex1 + newFaces.add edgeIndex2 + newFaces.add polytope.len + + polytope.add support + + var (newNormals, newMinFace) = getFaceNormals(polytope, newFaces) + if newNormals.len == 0: + break + + var oldMinDistance = high(float32) + for j in 0 ..< normals.len: + if normals[j].w < oldMinDistance: + oldMinDistance = normals[j].w + minFace = j + + if (newNormals[newMinFace].w < oldMinDistance): + minFace = newMinFace + normals.len + + for f in newFaces: + faces.add f + for n in newNormals: + normals.add n + inc iterCount + + result = (normal: minNormal, penetrationDepth: minDistance + 0.001'f32) + + +func collisionPoint2D(polytopeIn: seq[Vec3f], a, b: Collider): tuple[normal: Vec3f, penetrationDepth: float32] = + var + polytope = polytopeIn + minIndex = 0 + minDistance = high(float32) + iterCount = 0 + minNormal: Vec2f + + while minDistance == high(float32) and iterCount < MAX_COLLISON_POINT_CALCULATION_ITERATIONS: + for i in 0 ..< polytope.len: + let + j = (i + 1) mod polytope.len + vertexI = polytope[i] + vertexJ = polytope[j] + ij = vertexJ - vertexI + var + normal = newVec2f(ij.y, -ij.x).normalized() + distance = normal.dot(vertexI) + + if (distance < 0): + distance *= -1'f32 + normal = normal * -1'f32 + + if distance < minDistance: + minDistance = distance + minNormal = normal + minIndex = j + + let + support = supportPoint(a, b, minNormal.toVec3) + sDistance = minNormal.dot(support) + + if(abs(sDistance - minDistance) > 0.001): + minDistance = high(float32) + polytope.insert(support, minIndex) + inc iterCount + + result = (normal: newVec3f(minNormal.x, minNormal.y), penetrationDepth: minDistance + 0.001'f32) + +func intersects*(a, b: Collider, as2D=false): bool = + var + support = supportPoint(a, b, newVec3f(0.8153, -0.4239, if as2D: 0.0 else: 0.5786)) # just random initial vector + simplex = newSeq[Vec3f]() + direction = -support + n = 0 + simplex.insert(support, 0) + while n < MAX_COLLISON_DETECTION_ITERATIONS: + support = supportPoint(a, b, direction) + if support.dot(direction) <= 0: + return false + simplex.insert(support, 0) + if nextSimplex(simplex, direction, twoDimensional=as2D): + return true + # prevent numeric instability + if direction == newVec3f(0, 0, 0): + direction[0] = 0.0001 + inc n + +func collision*(a, b: Collider, as2D=false): tuple[hasCollision: bool, normal: Vec3f, penetrationDepth: float32] = + var + support = supportPoint(a, b, newVec3f(0.8153, -0.4239, if as2D: 0.0 else: 0.5786)) # just random initial vector + simplex = newSeq[Vec3f]() + direction = -support + n = 0 + simplex.insert(support, 0) + while n < MAX_COLLISON_DETECTION_ITERATIONS: + support = supportPoint(a, b, direction) + if support.dot(direction) <= 0: + return result + simplex.insert(support, 0) + if nextSimplex(simplex, direction, twoDimensional=as2D): + let (normal, depth) = if as2D: collisionPoint2D(simplex, a, b) else: collisionPoint3D(simplex, a, b) + return (true, normal, depth) + # prevent numeric instability + if direction == newVec3f(0, 0, 0): + direction[0] = 0.0001 + inc n + +func calculateCollider*(points: openArray[Vec3f], theType: ColliderType): Collider = + var + minX = high(float32) + maxX = low(float32) + minY = high(float32) + maxY = low(float32) + minZ = high(float32) + maxZ = low(float32) + center: Vec3f + + for p in points: + minX = min(minX, p.x) + maxX = max(maxX, p.x) + minY = min(minY, p.y) + maxY = max(maxY, p.y) + minZ = min(minZ, p.z) + maxZ = max(maxz, p.z) + center = center + p + center = center / float32(points.len) + + let + scaleX = (maxX - minX) + scaleY = (maxY - minY) + scaleZ = (maxZ - minZ) + + if theType == Points: + result = Collider(theType: Points, points: @points) + else: + result = Collider(theType: theType, transform: translate(minX, minY, minZ) * scale(scaleX, scaleY, scaleZ)) + + if theType == Sphere: + result.transform = translate(center) + for p in points: + result.radius = max(result.radius, (p - center).length) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,26 @@ +import std/math +export math + +import ./core/audiotypes +import ./core/fonttypes +import ./core/vulkanapi +import ./core/buildconfig +import ./core/color +import ./core/gpu_types +import ./core/dynamic_arrays +import ./core/imagetypes +import ./core/matrix +import ./core/vector +import ./core/utils + +export vulkanapi +export audiotypes +export fonttypes +export buildconfig +export color +export gpu_types +export dynamic_arrays +export imagetypes +export matrix +export vector +export utils diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/audiotypes.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/audiotypes.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,31 @@ +import std/math + +# in order to generate sound files that are directly usable with the engine, +# convert an audio file to a raw PCM signed 16 bit little endian file with 2 channels and 48kHz: +# +# ffmpeg -i -f s16le -ac 2 -ar 44100 -acodec pcm_s16le + +const AUDIO_SAMPLE_RATE* = 44100 + +type + Level* = 0'f .. 1'f + Sample* = array[2, int16] + SoundData* = seq[Sample] + Sound* = ref SoundData + +proc sinewave(f: float): proc(x: float): float = + proc ret(x: float): float = + sin(x * 2 * Pi * f) + result = ret + +proc sineSoundData*(f: float, len: float, rate: int): SoundData = + let dt = 1'f / float(rate) + var sine = sinewave(f) + for i in 0 ..< int(float(rate) * len): + let t = dt * float(i) + let value = int16(sine(t) * float(high(int16))) + result.add [value, value] + +proc newSound*(data: SoundData): Sound = + result = new Sound + result[] = data diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/buildconfig.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/buildconfig.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,62 @@ +import std/parsecfg +import std/streams +import std/strutils +import std/logging +import std/os + +const ENGINENAME* = "semicongine" +const ENGINEVERSION* = static: + let nimblePath = currentSourcePath.parentDir().parentDir().parentDir().joinPath("semicongine.nimble") + let nimbleFile = newStringStream(staticRead(nimblePath)) + let config = loadConfig(nimbleFile) + config.getSectionValue("", "version") + + +# checks required build options: +static: + assert compileOption("threads"), ENGINENAME & " requires --threads=on" + assert defined(nimPreviewHashRef), ENGINENAME & " requires -d:nimPreviewHashRef" + + if defined(release): + assert compileOption("app", "gui"), ENGINENAME & " requires --app=gui for release builds" + + + if defined(linux): + assert defined(VK_USE_PLATFORM_XLIB_KHR), ENGINENAME & " requires --d:VK_USE_PLATFORM_XLIB_KHR for linux builds" + elif defined(windows): + assert defined(VK_USE_PLATFORM_WIN32_KHR), ENGINENAME & " requires --d:VK_USE_PLATFORM_WIN32_KHR for windows builds" + else: + assert false, "trying to build on unsupported platform" + +# build configuration +# ===================== + +# compile-time defines, usefull for build-dependent settings +# can be overriden with compiler flags, e.g. -d:Foo=42 -d:Bar=false +# pramas: {.intdefine.} {.strdefine.} {.booldefine.} + +# root of where settings files will be searched +# must be relative (to the directory of the binary) +const DEBUG* = not defined(release) +const CONFIGROOT* {.strdefine.}: string = "." +assert not isAbsolute(CONFIGROOT) + +const CONFIGEXTENSION* {.strdefine.}: string = "ini" + +# by default enable hot-reload of runtime-configuration only in debug builds +const CONFIGHOTRELOAD* {.booldefine.}: bool = DEBUG + +# milliseconds to wait between checks for settings hotreload +const CONFIGHOTRELOADINTERVAL* {.intdefine.}: int = 1000 + +# log level +const LOGLEVEL {.strdefine.}: string = (when DEBUG: "lvlWarn" else: "lvlWarn") +const ENGINE_LOGLEVEL* = parseEnum[Level](LOGLEVEL) + +# resource bundleing settings, need to be configured per project +const RESOURCEROOT* {.strdefine.}: string = "" # should be the "mod" directory +const BUNDLETYPE* {.strdefine.}: string = "" # dir, zip, exe + +static: + assert RESOURCEROOT != "", ENGINENAME & " requires -d:RESOURCEROOT=resources" + assert BUNDLETYPE in ["dir", "zip", "exe"], ENGINENAME & " requires one of -d:BUNDLETYPE=dir -d:BUNDLETYPE=zip -d:BUNDLETYPE=exe" diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/color.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/color.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,58 @@ +import std/parseutils +import std/strformat + +import ./vector + + +func colorToHex*(color: Vec3f): string = + &"{int(color.r * 255):02X}{int(color.g * 255):02X}{int(color.b * 255):02X}" + +func colorToHex*(color: Vec4f): string = + &"{int(color.r * 255):02X}{int(color.g * 255):02X}{int(color.b * 255):02X}{int(color.a * 255):02X}" + +func asPixel*(color: Vec3f): array[4, uint8] = + [uint8(color.r * 255), uint8(color.g * 255), uint8(color.b * 255), 255'u8] +func asPixel*(color: Vec4f): array[4, uint8] = + [uint8(color.r * 255), uint8(color.g * 255), uint8(color.b * 255), uint8(color.a * 255)] + +func toRGBA*(value: string): Vec4f = + assert value != "" + var hex = value + if hex[0] == '#': + hex = hex[1 .. ^1] + # when 3 or 6 -> set alpha to 1.0 + assert hex.len == 3 or hex.len == 6 or hex.len == 4 or hex.len == 8 + if hex.len == 3: + hex = hex & "f" + if hex.len == 4: + hex = hex[0] & hex[0] & hex[1] & hex[1] & hex[2] & hex[2] & hex[3] & hex[3] + if hex.len == 6: + hex = hex & "ff" + assert hex.len == 8 + var r, g, b, a: uint8 + discard parseHex(hex[0 .. 1], r) + discard parseHex(hex[2 .. 3], g) + discard parseHex(hex[4 .. 5], b) + discard parseHex(hex[6 .. 7], a) + return Vec4f([float32(r), float32(g), float32(b), float32(a)]) / 255'f + +func gamma*[T: Vec3f|Vec4f](color: T, gamma: float32): T = + return pow(color, gamma) + +const + Black* = toRGBA "#000000FF" + Silver* = toRGBA "#C0C0C0FF" + Gray* = toRGBA "#808080FF" + White* = toRGBA "#FFFFFFFF" + Maroon* = toRGBA "#800000FF" + Red* = toRGBA "#FF0000FF" + Purple* = toRGBA "#800080FF" + Fuchsia* = toRGBA "#FF00FFFF" + Green* = toRGBA "#008000FF" + Lime* = toRGBA "#00FF00FF" + Olive* = toRGBA "#808000FF" + Yellow* = toRGBA "#FFFF00FF" + Navy* = toRGBA "#000080FF" + Blue* = toRGBA "#0000FFFF" + Teal* = toRGBA "#008080FF" + Aqua* = toRGBA "#00FFFFFF" diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/dynamic_arrays.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/dynamic_arrays.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,765 @@ +import std/hashes + +import ./gpu_types +import ./vector +import ./matrix +import ./utils +import ./imagetypes + +type + DataList* = object + len*: int + case theType*: DataType + of Float32: float32: ref seq[float32] + of Float64: float64: ref seq[float64] + of Int8: int8: ref seq[int8] + of Int16: int16: ref seq[int16] + of Int32: int32: ref seq[int32] + of Int64: int64: ref seq[int64] + of UInt8: uint8: ref seq[uint8] + of UInt16: uint16: ref seq[uint16] + of UInt32: uint32: ref seq[uint32] + of UInt64: uint64: ref seq[uint64] + of Vec2I32: vec2i32: ref seq[TVec2[int32]] + of Vec2I64: vec2i64: ref seq[TVec2[int64]] + of Vec3I32: vec3i32: ref seq[TVec3[int32]] + of Vec3I64: vec3i64: ref seq[TVec3[int64]] + of Vec4I32: vec4i32: ref seq[TVec4[int32]] + of Vec4I64: vec4i64: ref seq[TVec4[int64]] + of Vec2U32: vec2u32: ref seq[TVec2[uint32]] + of Vec2U64: vec2u64: ref seq[TVec2[uint64]] + of Vec3U32: vec3u32: ref seq[TVec3[uint32]] + of Vec3U64: vec3u64: ref seq[TVec3[uint64]] + of Vec4U32: vec4u32: ref seq[TVec4[uint32]] + of Vec4U64: vec4u64: ref seq[TVec4[uint64]] + of Vec2F32: vec2f32: ref seq[TVec2[float32]] + of Vec2F64: vec2f64: ref seq[TVec2[float64]] + of Vec3F32: vec3f32: ref seq[TVec3[float32]] + of Vec3F64: vec3f64: ref seq[TVec3[float64]] + of Vec4F32: vec4f32: ref seq[TVec4[float32]] + of Vec4F64: vec4f64: ref seq[TVec4[float64]] + of Mat2F32: mat2f32: ref seq[TMat2[float32]] + of Mat2F64: mat2f64: ref seq[TMat2[float64]] + of Mat23F32: mat23f32: ref seq[TMat23[float32]] + of Mat23F64: mat23f64: ref seq[TMat23[float64]] + of Mat32F32: mat32f32: ref seq[TMat32[float32]] + of Mat32F64: mat32f64: ref seq[TMat32[float64]] + of Mat3F32: mat3f32: ref seq[TMat3[float32]] + of Mat3F64: mat3f64: ref seq[TMat3[float64]] + of Mat34F32: mat34f32: ref seq[TMat34[float32]] + of Mat34F64: mat34f64: ref seq[TMat34[float64]] + of Mat43F32: mat43f32: ref seq[TMat43[float32]] + of Mat43F64: mat43f64: ref seq[TMat43[float64]] + of Mat4F32: mat4f32: ref seq[TMat4[float32]] + of Mat4F64: mat4f64: ref seq[TMat4[float64]] + of TextureType: texture: ref seq[Texture] + +func size*(value: DataList): int = + value.theType.size * value.len + +func hash*(value: DataList): Hash = + case value.theType + of Float32: hash(value.float32) + of Float64: hash(value.float64) + of Int8: hash(value.int8) + of Int16: hash(value.int16) + of Int32: hash(value.int32) + of Int64: hash(value.int64) + of UInt8: hash(value.uint8) + of UInt16: hash(value.uint16) + of UInt32: hash(value.uint32) + of UInt64: hash(value.uint64) + of Vec2I32: hash(value.vec2i32) + of Vec2I64: hash(value.vec2i64) + of Vec3I32: hash(value.vec3i32) + of Vec3I64: hash(value.vec3i64) + of Vec4I32: hash(value.vec4i32) + of Vec4I64: hash(value.vec4i64) + of Vec2U32: hash(value.vec2u32) + of Vec2U64: hash(value.vec2u64) + of Vec3U32: hash(value.vec3u32) + of Vec3U64: hash(value.vec3u64) + of Vec4U32: hash(value.vec4u32) + of Vec4U64: hash(value.vec4u64) + of Vec2F32: hash(value.vec2f32) + of Vec2F64: hash(value.vec2f64) + of Vec3F32: hash(value.vec3f32) + of Vec3F64: hash(value.vec3f64) + of Vec4F32: hash(value.vec4f32) + of Vec4F64: hash(value.vec4f64) + of Mat2F32: hash(value.mat2f32) + of Mat2F64: hash(value.mat2f64) + of Mat23F32: hash(value.mat23f32) + of Mat23F64: hash(value.mat23f64) + of Mat32F32: hash(value.mat32f32) + of Mat32F64: hash(value.mat32f64) + of Mat3F32: hash(value.mat3f32) + of Mat3F64: hash(value.mat3f64) + of Mat34F32: hash(value.mat34f32) + of Mat34F64: hash(value.mat34f64) + of Mat43F32: hash(value.mat43f32) + of Mat43F64: hash(value.mat43f64) + of Mat4F32: hash(value.mat4f32) + of Mat4F64: hash(value.mat4f64) + of TextureType: hash(value.texture) + +func `==`*(a, b: DataList): bool = + if a.theType != b.theType: + return false + case a.theType + of Float32: return a.float32 == b.float32 + of Float64: return a.float64 == b.float64 + of Int8: return a.int8 == b.int8 + of Int16: return a.int16 == b.int16 + of Int32: return a.int32 == b.int32 + of Int64: return a.int64 == b.int64 + of UInt8: return a.uint8 == b.uint8 + of UInt16: return a.uint16 == b.uint16 + of UInt32: return a.uint32 == b.uint32 + of UInt64: return a.uint64 == b.uint64 + of Vec2I32: return a.vec2i32 == b.vec2i32 + of Vec2I64: return a.vec2i64 == b.vec2i64 + of Vec3I32: return a.vec3i32 == b.vec3i32 + of Vec3I64: return a.vec3i64 == b.vec3i64 + of Vec4I32: return a.vec4i32 == b.vec4i32 + of Vec4I64: return a.vec4i64 == b.vec4i64 + of Vec2U32: return a.vec2u32 == b.vec2u32 + of Vec2U64: return a.vec2u64 == b.vec2u64 + of Vec3U32: return a.vec3u32 == b.vec3u32 + of Vec3U64: return a.vec3u64 == b.vec3u64 + of Vec4U32: return a.vec4u32 == b.vec4u32 + of Vec4U64: return a.vec4u64 == b.vec4u64 + of Vec2F32: return a.vec2f32 == b.vec2f32 + of Vec2F64: return a.vec2f64 == b.vec2f64 + of Vec3F32: return a.vec3f32 == b.vec3f32 + of Vec3F64: return a.vec3f64 == b.vec3f64 + of Vec4F32: return a.vec4f32 == b.vec4f32 + of Vec4F64: return a.vec4f64 == b.vec4f64 + of Mat2F32: return a.mat2f32 == b.mat2f32 + of Mat2F64: return a.mat2f64 == b.mat2f64 + of Mat23F32: return a.mat23f32 == b.mat23f32 + of Mat23F64: return a.mat23f64 == b.mat23f64 + of Mat32F32: return a.mat32f32 == b.mat32f32 + of Mat32F64: return a.mat32f64 == b.mat32f64 + of Mat3F32: return a.mat3f32 == b.mat3f32 + of Mat3F64: return a.mat3f64 == b.mat3f64 + of Mat34F32: return a.mat34f32 == b.mat34f32 + of Mat34F64: return a.mat34f64 == b.mat34f64 + of Mat43F32: return a.mat43f32 == b.mat43f32 + of Mat43F64: return a.mat43f64 == b.mat43f64 + of Mat4F32: return a.mat4f32 == b.mat4f32 + of Mat4F64: return a.mat4f64 == b.mat4f64 + of TextureType: a.texture == b.texture + +proc setLen*(value: var DataList, len: int) = + value.len = len + case value.theType + of Float32: value.float32[].setLen(len) + of Float64: value.float64[].setLen(len) + of Int8: value.int8[].setLen(len) + of Int16: value.int16[].setLen(len) + of Int32: value.int32[].setLen(len) + of Int64: value.int64[].setLen(len) + of UInt8: value.uint8[].setLen(len) + of UInt16: value.uint16[].setLen(len) + of UInt32: value.uint32[].setLen(len) + of UInt64: value.uint64[].setLen(len) + of Vec2I32: value.vec2i32[].setLen(len) + of Vec2I64: value.vec2i64[].setLen(len) + of Vec3I32: value.vec3i32[].setLen(len) + of Vec3I64: value.vec3i64[].setLen(len) + of Vec4I32: value.vec4i32[].setLen(len) + of Vec4I64: value.vec4i64[].setLen(len) + of Vec2U32: value.vec2u32[].setLen(len) + of Vec2U64: value.vec2u64[].setLen(len) + of Vec3U32: value.vec3u32[].setLen(len) + of Vec3U64: value.vec3u64[].setLen(len) + of Vec4U32: value.vec4u32[].setLen(len) + of Vec4U64: value.vec4u64[].setLen(len) + of Vec2F32: value.vec2f32[].setLen(len) + of Vec2F64: value.vec2f64[].setLen(len) + of Vec3F32: value.vec3f32[].setLen(len) + of Vec3F64: value.vec3f64[].setLen(len) + of Vec4F32: value.vec4f32[].setLen(len) + of Vec4F64: value.vec4f64[].setLen(len) + of Mat2F32: value.mat2f32[].setLen(len) + of Mat2F64: value.mat2f64[].setLen(len) + of Mat23F32: value.mat23f32[].setLen(len) + of Mat23F64: value.mat23f64[].setLen(len) + of Mat32F32: value.mat32f32[].setLen(len) + of Mat32F64: value.mat32f64[].setLen(len) + of Mat3F32: value.mat3f32[].setLen(len) + of Mat3F64: value.mat3f64[].setLen(len) + of Mat34F32: value.mat34f32[].setLen(len) + of Mat34F64: value.mat34f64[].setLen(len) + of Mat43F32: value.mat43f32[].setLen(len) + of Mat43F64: value.mat43f64[].setLen(len) + of Mat4F32: value.mat4f32[].setLen(len) + of Mat4F64: value.mat4f64[].setLen(len) + of TextureType: discard + + +proc setValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = + value.setLen(data.len) + when T is float32: value.float32[] = data + elif T is float64: value.float64[] = data + elif T is int8: value.int8[] = data + elif T is int16: value.int16[] = data + elif T is int32: value.int32[] = data + elif T is int64: value.int64[] = data + elif T is uint8: value.uint8[] = data + elif T is uint16: value.uint16[] = data + elif T is uint32: value.uint32[] = data + elif T is uint64: value.uint64[] = data + elif T is int and sizeof(int) == sizeof(int32): value.int32[] = data + elif T is int and sizeof(int) == sizeof(int64): value.int64[] = data + elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[] = data + elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[] = data + elif T is float and sizeof(float) == sizeof(float32): value.float32[] = data + elif T is float and sizeof(float) == sizeof(float64): value.float64[] = data + elif T is TVec2[int32]: value.vec2i32[] = data + elif T is TVec2[int64]: value.vec2i64[] = data + elif T is TVec3[int32]: value.vec3i32[] = data + elif T is TVec3[int64]: value.vec3i64[] = data + elif T is TVec4[int32]: value.vec4i32[] = data + elif T is TVec4[int64]: value.vec4i64[] = data + elif T is TVec2[uint32]: value.vec2u32[] = data + elif T is TVec2[uint64]: value.vec2u64[] = data + elif T is TVec3[uint32]: value.vec3u32[] = data + elif T is TVec3[uint64]: value.vec3u64[] = data + elif T is TVec4[uint32]: value.vec4u32[] = data + elif T is TVec4[uint64]: value.vec4u64[] = data + elif T is TVec2[float32]: value.vec2f32[] = data + elif T is TVec2[float64]: value.vec2f64[] = data + elif T is TVec3[float32]: value.vec3f32[] = data + elif T is TVec3[float64]: value.vec3f64[] = data + elif T is TVec4[float32]: value.vec4f32[] = data + elif T is TVec4[float64]: value.vec4f64[] = data + elif T is TMat2[float32]: value.mat2f32[] = data + elif T is TMat2[float64]: value.mat2f64[] = data + elif T is TMat23[float32]: value.mat23f32[] = data + elif T is TMat23[float64]: value.mat23f64[] = data + elif T is TMat32[float32]: value.mat32f32[] = data + elif T is TMat32[float64]: value.mat32f64[] = data + elif T is TMat3[float32]: value.mat3f32[] = data + elif T is TMat3[float64]: value.mat3f64[] = data + elif T is TMat34[float32]: value.mat34f32[] = data + elif T is TMat34[float64]: value.mat34f64[] = data + elif T is TMat43[float32]: value.mat43f32[] = data + elif T is TMat43[float64]: value.mat43f64[] = data + elif T is TMat4[float32]: value.mat4f32[] = data + elif T is TMat4[float64]: value.mat4f64[] = data + elif T is Texture: value.texture[] = data + else: {. error: "Virtual datatype has no values" .} + +proc initDataList*(theType: DataType, len=1): DataList = + result = DataList(theType: theType) + case result.theType + of Float32: result.float32 = new seq[float32] + of Float64: result.float64 = new seq[float64] + of Int8: result.int8 = new seq[int8] + of Int16: result.int16 = new seq[int16] + of Int32: result.int32 = new seq[int32] + of Int64: result.int64 = new seq[int64] + of UInt8: result.uint8 = new seq[uint8] + of UInt16: result.uint16 = new seq[uint16] + of UInt32: result.uint32 = new seq[uint32] + of UInt64: result.uint64 = new seq[uint64] + of Vec2I32: result.vec2i32 = new seq[TVec2[int32]] + of Vec2I64: result.vec2i64 = new seq[TVec2[int64]] + of Vec3I32: result.vec3i32 = new seq[TVec3[int32]] + of Vec3I64: result.vec3i64 = new seq[TVec3[int64]] + of Vec4I32: result.vec4i32 = new seq[TVec4[int32]] + of Vec4I64: result.vec4i64 = new seq[TVec4[int64]] + of Vec2U32: result.vec2u32 = new seq[TVec2[uint32]] + of Vec2U64: result.vec2u64 = new seq[TVec2[uint64]] + of Vec3U32: result.vec3u32 = new seq[TVec3[uint32]] + of Vec3U64: result.vec3u64 = new seq[TVec3[uint64]] + of Vec4U32: result.vec4u32 = new seq[TVec4[uint32]] + of Vec4U64: result.vec4u64 = new seq[TVec4[uint64]] + of Vec2F32: result.vec2f32 = new seq[TVec2[float32]] + of Vec2F64: result.vec2f64 = new seq[TVec2[float64]] + of Vec3F32: result.vec3f32 = new seq[TVec3[float32]] + of Vec3F64: result.vec3f64 = new seq[TVec3[float64]] + of Vec4F32: result.vec4f32 = new seq[TVec4[float32]] + of Vec4F64: result.vec4f64 = new seq[TVec4[float64]] + of Mat2F32: result.mat2f32 = new seq[TMat2[float32]] + of Mat2F64: result.mat2f64 = new seq[TMat2[float64]] + of Mat23F32: result.mat23f32 = new seq[TMat23[float32]] + of Mat23F64: result.mat23f64 = new seq[TMat23[float64]] + of Mat32F32: result.mat32f32 = new seq[TMat32[float32]] + of Mat32F64: result.mat32f64 = new seq[TMat32[float64]] + of Mat3F32: result.mat3f32 = new seq[TMat3[float32]] + of Mat3F64: result.mat3f64 = new seq[TMat3[float64]] + of Mat34F32: result.mat34f32 = new seq[TMat34[float32]] + of Mat34F64: result.mat34f64 = new seq[TMat34[float64]] + of Mat43F32: result.mat43f32 = new seq[TMat43[float32]] + of Mat43F64: result.mat43f64 = new seq[TMat43[float64]] + of Mat4F32: result.mat4f32 = new seq[TMat4[float32]] + of Mat4F64: result.mat4f64 = new seq[TMat4[float64]] + of TextureType: result.texture = new seq[Texture] + result.setLen(len) + +proc initDataList*[T: GPUType](len=1): DataList = + result = initDataList(getDataType[T]()) + result.setLen(len) + +proc initDataList*[T: GPUType](data: openArray[T]): DataList = + result = initDataList(getDataType[T]()) + result.setValues(@data) + +func getValues*[T: GPUType|int|uint|float](value: DataList): ref seq[T] = + when T is float32: value.float32 + elif T is float64: value.float64 + elif T is int8: value.int8 + elif T is int16: value.int16 + elif T is int32: value.int32 + elif T is int64: value.int64 + elif T is uint8: value.uint8 + elif T is uint16: value.uint16 + elif T is uint32: value.uint32 + elif T is uint64: value.uint64 + elif T is int and sizeof(int) == sizeof(int32): value.int32 + elif T is int and sizeof(int) == sizeof(int64): value.int64 + elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32 + elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64 + elif T is float and sizeof(float) == sizeof(float32): value.float32 + elif T is float and sizeof(float) == sizeof(float64): value.float64 + elif T is TVec2[int32]: value.vec2i32 + elif T is TVec2[int64]: value.vec2i64 + elif T is TVec3[int32]: value.vec3i32 + elif T is TVec3[int64]: value.vec3i64 + elif T is TVec4[int32]: value.vec4i32 + elif T is TVec4[int64]: value.vec4i64 + elif T is TVec2[uint32]: value.vec2u32 + elif T is TVec2[uint64]: value.vec2u64 + elif T is TVec3[uint32]: value.vec3u32 + elif T is TVec3[uint64]: value.vec3u64 + elif T is TVec4[uint32]: value.vec4u32 + elif T is TVec4[uint64]: value.vec4u64 + elif T is TVec2[float32]: value.vec2f32 + elif T is TVec2[float64]: value.vec2f64 + elif T is TVec3[float32]: value.vec3f32 + elif T is TVec3[float64]: value.vec3f64 + elif T is TVec4[float32]: value.vec4f32 + elif T is TVec4[float64]: value.vec4f64 + elif T is TMat2[float32]: value.mat2f32 + elif T is TMat2[float64]: value.mat2f64 + elif T is TMat23[float32]: value.mat23f + elif T is TMat23[float64]: value.mat23f64 + elif T is TMat32[float32]: value.mat32f32 + elif T is TMat32[float64]: value.mat32f64 + elif T is TMat3[float32]: value.mat3f32 + elif T is TMat3[float64]: value.mat3f64 + elif T is TMat34[float32]: value.mat34f32 + elif T is TMat34[float64]: value.mat34f64 + elif T is TMat43[float32]: value.mat43f32 + elif T is TMat43[float64]: value.mat43f64 + elif T is TMat4[float32]: value.mat4f32 + elif T is TMat4[float64]: value.mat4f64 + elif T is Texture: value.texture + else: {. error: "Virtual datatype has no values" .} + +func getValue*[T: GPUType|int|uint|float](value: DataList, i: int): T = + when T is float32: value.float32[i] + elif T is float64: value.float64[i] + elif T is int8: value.int8[i] + elif T is int16: value.int16[i] + elif T is int32: value.int32[i] + elif T is int64: value.int64[i] + elif T is uint8: value.uint8[i] + elif T is uint16: value.uint16[i] + elif T is uint32: value.uint32[i] + elif T is uint64: value.uint64[i] + elif T is int and sizeof(int) == sizeof(int32): value.int32[i] + elif T is int and sizeof(int) == sizeof(int64): value.int64[i] + elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[i] + elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[i] + elif T is float and sizeof(float) == sizeof(float32): value.float32[i] + elif T is float and sizeof(float) == sizeof(float64): value.float64[i] + elif T is TVec2[int32]: value.vec2i32[i] + elif T is TVec2[int64]: value.vec2i64[i] + elif T is TVec3[int32]: value.vec3i32[i] + elif T is TVec3[int64]: value.vec3i64[i] + elif T is TVec4[int32]: value.vec4i32[i] + elif T is TVec4[int64]: value.vec4i64[i] + elif T is TVec2[uint32]: value.vec2u32[i] + elif T is TVec2[uint64]: value.vec2u64[i] + elif T is TVec3[uint32]: value.vec3u32[i] + elif T is TVec3[uint64]: value.vec3u64[i] + elif T is TVec4[uint32]: value.vec4u32[i] + elif T is TVec4[uint64]: value.vec4u64[i] + elif T is TVec2[float32]: value.vec2f32[i] + elif T is TVec2[float64]: value.vec2f64[i] + elif T is TVec3[float32]: value.vec3f32[i] + elif T is TVec3[float64]: value.vec3f64[i] + elif T is TVec4[float32]: value.vec4f32[i] + elif T is TVec4[float64]: value.vec4f64[i] + elif T is TMat2[float32]: value.mat2f32[i] + elif T is TMat2[float64]: value.mat2f64[i] + elif T is TMat23[float32]: value.mat23f[i] + elif T is TMat23[float64]: value.mat23f64[i] + elif T is TMat32[float32]: value.mat32f32[i] + elif T is TMat32[float64]: value.mat32f64[i] + elif T is TMat3[float32]: value.mat3f32[i] + elif T is TMat3[float64]: value.mat3f64[i] + elif T is TMat34[float32]: value.mat34f32[i] + elif T is TMat34[float64]: value.mat34f64[i] + elif T is TMat43[float32]: value.mat43f32[i] + elif T is TMat43[float64]: value.mat43f64[i] + elif T is TMat4[float32]: value.mat4f32[i] + elif T is TMat4[float64]: value.mat4f64[i] + elif T is Texture: value.texture[i] + else: {. error: "Virtual datatype has no values" .} + +func getRawData*(value: var DataList): (pointer, int) = + if value.len == 0: + return (nil, 0) + result[1] = value.theType.size * value.len + case value.theType + of Float32: result[0] = value.float32[].toCPointer + of Float64: result[0] = value.float64[].toCPointer + of Int8: result[0] = value.int8[].toCPointer + of Int16: result[0] = value.int16[].toCPointer + of Int32: result[0] = value.int32[].toCPointer + of Int64: result[0] = value.int64[].toCPointer + of UInt8: result[0] = value.uint8[].toCPointer + of UInt16: result[0] = value.uint16[].toCPointer + of UInt32: result[0] = value.uint32[].toCPointer + of UInt64: result[0] = value.uint64[].toCPointer + of Vec2I32: result[0] = value.vec2i32[].toCPointer + of Vec2I64: result[0] = value.vec2i64[].toCPointer + of Vec3I32: result[0] = value.vec3i32[].toCPointer + of Vec3I64: result[0] = value.vec3i64[].toCPointer + of Vec4I32: result[0] = value.vec4i32[].toCPointer + of Vec4I64: result[0] = value.vec4i64[].toCPointer + of Vec2U32: result[0] = value.vec2u32[].toCPointer + of Vec2U64: result[0] = value.vec2u64[].toCPointer + of Vec3U32: result[0] = value.vec3u32[].toCPointer + of Vec3U64: result[0] = value.vec3u64[].toCPointer + of Vec4U32: result[0] = value.vec4u32[].toCPointer + of Vec4U64: result[0] = value.vec4u64[].toCPointer + of Vec2F32: result[0] = value.vec2f32[].toCPointer + of Vec2F64: result[0] = value.vec2f64[].toCPointer + of Vec3F32: result[0] = value.vec3f32[].toCPointer + of Vec3F64: result[0] = value.vec3f64[].toCPointer + of Vec4F32: result[0] = value.vec4f32[].toCPointer + of Vec4F64: result[0] = value.vec4f64[].toCPointer + of Mat2F32: result[0] = value.mat2f32[].toCPointer + of Mat2F64: result[0] = value.mat2f64[].toCPointer + of Mat23F32: result[0] = value.mat23f32[].toCPointer + of Mat23F64: result[0] = value.mat23f64[].toCPointer + of Mat32F32: result[0] = value.mat32f32[].toCPointer + of Mat32F64: result[0] = value.mat32f64[].toCPointer + of Mat3F32: result[0] = value.mat3f32[].toCPointer + of Mat3F64: result[0] = value.mat3f64[].toCPointer + of Mat34F32: result[0] = value.mat34f32[].toCPointer + of Mat34F64: result[0] = value.mat34f64[].toCPointer + of Mat43F32: result[0] = value.mat43f32[].toCPointer + of Mat43F64: result[0] = value.mat43f64[].toCPointer + of Mat4F32: result[0] = value.mat4f32[].toCPointer + of Mat4F64: result[0] = value.mat4f64[].toCPointer + of TextureType: result[0] = nil + +proc appendValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = + value.len += data.len + when T is float32: value.float32[].add data + elif T is float64: value.float64[].add data + elif T is int8: value.int8[].add data + elif T is int16: value.int16[].add data + elif T is int32: value.int32[].add data + elif T is int64: value.int64[].add data + elif T is uint8: value.uint8[].add data + elif T is uint16: value.uint16[].add data + elif T is uint32: value.uint32[].add data + elif T is uint64: value.uint64[].add data + elif T is int and sizeof(int) == sizeof(int32): value.int32[].add data + elif T is int and sizeof(int) == sizeof(int64): value.int64[].add data + elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[].add data + elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[].add data + elif T is float and sizeof(float) == sizeof(float32): value.float32[].add data + elif T is float and sizeof(float) == sizeof(float64): value.float64[].add data + elif T is TVec2[int32]: value.vec2i32[].add data + elif T is TVec2[int64]: value.vec2i64[].add data + elif T is TVec3[int32]: value.vec3i32[].add data + elif T is TVec3[int64]: value.vec3i64[].add data + elif T is TVec4[int32]: value.vec4i32[].add data + elif T is TVec4[int64]: value.vec4i64[].add data + elif T is TVec2[uint32]: value.vec2u32[].add data + elif T is TVec2[uint64]: value.vec2u64[].add data + elif T is TVec3[uint32]: value.vec3u32[].add data + elif T is TVec3[uint64]: value.vec3u64[].add data + elif T is TVec4[uint32]: value.vec4u32[].add data + elif T is TVec4[uint64]: value.vec4u64[].add data + elif T is TVec2[float32]: value.vec2f32[].add data + elif T is TVec2[float64]: value.vec2f64[].add data + elif T is TVec3[float32]: value.vec3f32[].add data + elif T is TVec3[float64]: value.vec3f64[].add data + elif T is TVec4[float32]: value.vec4f32[].add data + elif T is TVec4[float64]: value.vec4f64[].add data + elif T is TMat2[float32]: value.mat2f32[].add data + elif T is TMat2[float64]: value.mat2f64[].add data + elif T is TMat23[float32]: value.mat23f32[].add data + elif T is TMat23[float64]: value.mat23f64[].add data + elif T is TMat32[float32]: value.mat32f32[].add data + elif T is TMat32[float64]: value.mat32f64[].add data + elif T is TMat3[float32]: value.mat3f32[].add data + elif T is TMat3[float64]: value.mat3f64[].add data + elif T is TMat34[float32]: value.mat34f32[].add data + elif T is TMat34[float64]: value.mat34f64[].add data + elif T is TMat43[float32]: value.mat43f32[].add data + elif T is TMat43[float64]: value.mat43f64[].add data + elif T is TMat4[float32]: value.mat4f32[].add data + elif T is TMat4[float64]: value.mat4f64[].add data + elif T is Texture: value.texture[].add data + else: {. error: "Virtual datatype has no values" .} + +proc appendValues*(value: var DataList, data: DataList) = + assert value.theType == data.theType + value.len += data.len + case value.theType: + of Float32: value.float32[].add data.float32[] + of Float64: value.float64[].add data.float64[] + of Int8: value.int8[].add data.int8[] + of Int16: value.int16[].add data.int16[] + of Int32: value.int32[].add data.int32[] + of Int64: value.int64[].add data.int64[] + of UInt8: value.uint8[].add data.uint8[] + of UInt16: value.uint16[].add data.uint16[] + of UInt32: value.uint32[].add data.uint32[] + of UInt64: value.uint64[].add data.uint64[] + of Vec2I32: value.vec2i32[].add data.vec2i32[] + of Vec2I64: value.vec2i64[].add data.vec2i64[] + of Vec3I32: value.vec3i32[].add data.vec3i32[] + of Vec3I64: value.vec3i64[].add data.vec3i64[] + of Vec4I32: value.vec4i32[].add data.vec4i32[] + of Vec4I64: value.vec4i64[].add data.vec4i64[] + of Vec2U32: value.vec2u32[].add data.vec2u32[] + of Vec2U64: value.vec2u64[].add data.vec2u64[] + of Vec3U32: value.vec3u32[].add data.vec3u32[] + of Vec3U64: value.vec3u64[].add data.vec3u64[] + of Vec4U32: value.vec4u32[].add data.vec4u32[] + of Vec4U64: value.vec4u64[].add data.vec4u64[] + of Vec2F32: value.vec2f32[].add data.vec2f32[] + of Vec2F64: value.vec2f64[].add data.vec2f64[] + of Vec3F32: value.vec3f32[].add data.vec3f32[] + of Vec3F64: value.vec3f64[].add data.vec3f64[] + of Vec4F32: value.vec4f32[].add data.vec4f32[] + of Vec4F64: value.vec4f64[].add data.vec4f64[] + of Mat2F32: value.mat2f32[].add data.mat2f32[] + of Mat2F64: value.mat2f64[].add data.mat2f64[] + of Mat23F32: value.mat23f32[].add data.mat23f32[] + of Mat23F64: value.mat23f64[].add data.mat23f64[] + of Mat32F32: value.mat32f32[].add data.mat32f32[] + of Mat32F64: value.mat32f64[].add data.mat32f64[] + of Mat3F32: value.mat3f32[].add data.mat3f32[] + of Mat3F64: value.mat3f64[].add data.mat3f64[] + of Mat34F32: value.mat34f32[].add data.mat34f32[] + of Mat34F64: value.mat34f64[].add data.mat34f64[] + of Mat43F32: value.mat43f32[].add data.mat43f32[] + of Mat43F64: value.mat43f64[].add data.mat43f64[] + of Mat4F32: value.mat4f32[].add data.mat4f32[] + of Mat4F64: value.mat4f64[].add data.mat4f64[] + of TextureType: value.texture[].add data.texture[] + +proc setValue*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = + when T is float32: value.float32[] = data + elif T is float64: value.float64[] = data + elif T is int8: value.int8[] = data + elif T is int16: value.int16[] = data + elif T is int32: value.int32[] = data + elif T is int64: value.int64[] = data + elif T is uint8: value.uint8[] = data + elif T is uint16: value.uint16[] = data + elif T is uint32: value.uint32[] = data + elif T is uint64: value.uint64[] = data + elif T is int and sizeof(int) == sizeof(int32): value.int32[] = data + elif T is int and sizeof(int) == sizeof(int64): value.int64[] = data + elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[] = data + elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[] = data + elif T is float and sizeof(float) == sizeof(float32): value.float32[] = data + elif T is float and sizeof(float) == sizeof(float64): value.float64[] = data + elif T is TVec2[int32]: value.vec2i32[] = data + elif T is TVec2[int64]: value.vec2i64[] = data + elif T is TVec3[int32]: value.vec3i32[] = data + elif T is TVec3[int64]: value.vec3i64[] = data + elif T is TVec4[int32]: value.vec4i32[] = data + elif T is TVec4[int64]: value.vec4i64[] = data + elif T is TVec2[uint32]: value.vec2u32[] = data + elif T is TVec2[uint64]: value.vec2u64[] = data + elif T is TVec3[uint32]: value.vec3u32[] = data + elif T is TVec3[uint64]: value.vec3u64[] = data + elif T is TVec4[uint32]: value.vec4u32[] = data + elif T is TVec4[uint64]: value.vec4u64[] = data + elif T is TVec2[float32]: value.vec2f32[] = data + elif T is TVec2[float64]: value.vec2f64[] = data + elif T is TVec3[float32]: value.vec3f32[] = data + elif T is TVec3[float64]: value.vec3f64[] = data + elif T is TVec4[float32]: value.vec4f32[] = data + elif T is TVec4[float64]: value.vec4f64[] = data + elif T is TMat2[float32]: value.mat2f32[] = data + elif T is TMat2[float64]: value.mat2f64[] = data + elif T is TMat23[float32]: value.mat23f32[] = data + elif T is TMat23[float64]: value.mat23f64[] = data + elif T is TMat32[float32]: value.mat32f32[] = data + elif T is TMat32[float64]: value.mat32f64[] = data + elif T is TMat3[float32]: value.mat3f32[] = data + elif T is TMat3[float64]: value.mat3f64[] = data + elif T is TMat34[float32]: value.mat34f32[] = data + elif T is TMat34[float64]: value.mat34f64[] = data + elif T is TMat43[float32]: value.mat43f32[] = data + elif T is TMat43[float64]: value.mat43f64[] = data + elif T is TMat4[float32]: value.mat4f32[] = data + elif T is TMat4[float64]: value.mat4f64[] = data + elif T is Texture: value.texture[] = data + else: {. error: "Virtual datatype has no values" .} + +proc setValue*[T: GPUType|int|uint|float](value: var DataList, i: int, data: T) = + assert i < value.len + when T is float32: value.float32[i] = data + elif T is float64: value.float64[i] = data + elif T is int8: value.int8[i] = data + elif T is int16: value.int16[i] = data + elif T is int32: value.int32[i] = data + elif T is int64: value.int64[i] = data + elif T is uint8: value.uint8[i] = data + elif T is uint16: value.uint16[i] = data + elif T is uint32: value.uint32[i] = data + elif T is uint64: value.uint64[i] = data + elif T is int and sizeof(int) == sizeof(int32): value.int32[i] = data + elif T is int and sizeof(int) == sizeof(int64): value.int64[i] = data + elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[i] = data + elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[i] = data + elif T is float and sizeof(float) == sizeof(float32): value.float32[i] = data + elif T is float and sizeof(float) == sizeof(float64): value.float64[i] = data + elif T is TVec2[int32]: value.vec2i32[i] = data + elif T is TVec2[int64]: value.vec2i64[i] = data + elif T is TVec3[int32]: value.vec3i32[i] = data + elif T is TVec3[int64]: value.vec3i64[i] = data + elif T is TVec4[int32]: value.vec4i32[i] = data + elif T is TVec4[int64]: value.vec4i64[i] = data + elif T is TVec2[uint32]: value.vec2u32[i] = data + elif T is TVec2[uint64]: value.vec2u64[i] = data + elif T is TVec3[uint32]: value.vec3u32[i] = data + elif T is TVec3[uint64]: value.vec3u64[i] = data + elif T is TVec4[uint32]: value.vec4u32[i] = data + elif T is TVec4[uint64]: value.vec4u64[i] = data + elif T is TVec2[float32]: value.vec2f32[i] = data + elif T is TVec2[float64]: value.vec2f64[i] = data + elif T is TVec3[float32]: value.vec3f32[i] = data + elif T is TVec3[float64]: value.vec3f64[i] = data + elif T is TVec4[float32]: value.vec4f32[i] = data + elif T is TVec4[float64]: value.vec4f64[i] = data + elif T is TMat2[float32]: value.mat2f32[i] = data + elif T is TMat2[float64]: value.mat2f64[i] = data + elif T is TMat23[float32]: value.mat23f32[i] = data + elif T is TMat23[float64]: value.mat23f64[i] = data + elif T is TMat32[float32]: value.mat32f32[i] = data + elif T is TMat32[float64]: value.mat32f64[i] = data + elif T is TMat3[float32]: value.mat3f32[i] = data + elif T is TMat3[float64]: value.mat3f64[i] = data + elif T is TMat34[float32]: value.mat34f32[i] = data + elif T is TMat34[float64]: value.mat34f64[i] = data + elif T is TMat43[float32]: value.mat43f32[i] = data + elif T is TMat43[float64]: value.mat43f64[i] = data + elif T is TMat4[float32]: value.mat4f32[i] = data + elif T is TMat4[float64]: value.mat4f64[i] = data + elif T is Texture: value.texture[i] = data + else: {. error: "Virtual datatype has no values" .} + +proc appendFrom*(a: var DataList, i: int, b: DataList, j: int) = + assert a.theType == b.theType + case a.theType + of Float32: a.float32[i] = b.float32[j] + of Float64: a.float64[i] = b.float64[j] + of Int8: a.int8[i] = b.int8[j] + of Int16: a.int16[i] = b.int16[j] + of Int32: a.int32[i] = b.int32[j] + of Int64: a.int64[i] = b.int64[j] + of UInt8: a.uint8[i] = b.uint8[j] + of UInt16: a.uint16[i] = b.uint16[j] + of UInt32: a.uint32[i] = b.uint32[j] + of UInt64: a.uint64[i] = b.uint64[j] + of Vec2I32: a.vec2i32[i] = b.vec2i32[j] + of Vec2I64: a.vec2i64[i] = b.vec2i64[j] + of Vec3I32: a.vec3i32[i] = b.vec3i32[j] + of Vec3I64: a.vec3i64[i] = b.vec3i64[j] + of Vec4I32: a.vec4i32[i] = b.vec4i32[j] + of Vec4I64: a.vec4i64[i] = b.vec4i64[j] + of Vec2U32: a.vec2u32[i] = b.vec2u32[j] + of Vec2U64: a.vec2u64[i] = b.vec2u64[j] + of Vec3U32: a.vec3u32[i] = b.vec3u32[j] + of Vec3U64: a.vec3u64[i] = b.vec3u64[j] + of Vec4U32: a.vec4u32[i] = b.vec4u32[j] + of Vec4U64: a.vec4u64[i] = b.vec4u64[j] + of Vec2F32: a.vec2f32[i] = b.vec2f32[j] + of Vec2F64: a.vec2f64[i] = b.vec2f64[j] + of Vec3F32: a.vec3f32[i] = b.vec3f32[j] + of Vec3F64: a.vec3f64[i] = b.vec3f64[j] + of Vec4F32: a.vec4f32[i] = b.vec4f32[j] + of Vec4F64: a.vec4f64[i] = b.vec4f64[j] + of Mat2F32: a.mat2f32[i] = b.mat2f32[j] + of Mat2F64: a.mat2f64[i] = b.mat2f64[j] + of Mat23F32: a.mat23f32[i] = b.mat23f32[j] + of Mat23F64: a.mat23f64[i] = b.mat23f64[j] + of Mat32F32: a.mat32f32[i] = b.mat32f32[j] + of Mat32F64: a.mat32f64[i] = b.mat32f64[j] + of Mat3F32: a.mat3f32[i] = b.mat3f32[j] + of Mat3F64: a.mat3f64[i] = b.mat3f64[j] + of Mat34F32: a.mat34f32[i] = b.mat34f32[j] + of Mat34F64: a.mat34f64[i] = b.mat34f64[j] + of Mat43F32: a.mat43f32[i] = b.mat43f32[j] + of Mat43F64: a.mat43f64[i] = b.mat43f64[j] + of Mat4F32: a.mat4f32[i] = b.mat4f32[j] + of Mat4F64: a.mat4f64[i] = b.mat4f64[j] + of TextureType: a.texture[i] = b.texture[j] + +proc copy*(datalist: DataList): DataList = + result = initDataList(datalist.theType) + result.appendValues(datalist) + +func `$`*(list: DataList): string = + case list.theType + of Float32: $list.float32[] + of Float64: $list.float64[] + of Int8: $list.int8[] + of Int16: $list.int16[] + of Int32: $list.int32[] + of Int64: $list.int64[] + of UInt8: $list.uint8[] + of UInt16: $list.uint16[] + of UInt32: $list.uint32[] + of UInt64: $list.uint64[] + of Vec2I32: $list.vec2i32[] + of Vec2I64: $list.vec2i64[] + of Vec3I32: $list.vec3i32[] + of Vec3I64: $list.vec3i64[] + of Vec4I32: $list.vec4i32[] + of Vec4I64: $list.vec4i64[] + of Vec2U32: $list.vec2u32[] + of Vec2U64: $list.vec2u64[] + of Vec3U32: $list.vec3u32[] + of Vec3U64: $list.vec3u64[] + of Vec4U32: $list.vec4u32[] + of Vec4U64: $list.vec4u64[] + of Vec2F32: $list.vec2f32[] + of Vec2F64: $list.vec2f64[] + of Vec3F32: $list.vec3f32[] + of Vec3F64: $list.vec3f64[] + of Vec4F32: $list.vec4f32[] + of Vec4F64: $list.vec4f64[] + of Mat2F32: $list.mat2f32[] + of Mat2F64: $list.mat2f64[] + of Mat23F32: $list.mat23f32[] + of Mat23F64: $list.mat23f64[] + of Mat32F32: $list.mat32f32[] + of Mat32F64: $list.mat32f64[] + of Mat3F32: $list.mat3f32[] + of Mat3F64: $list.mat3f64[] + of Mat34F32: $list.mat34f32[] + of Mat34F64: $list.mat34f64[] + of Mat43F32: $list.mat43f32[] + of Mat43F64: $list.mat43f64[] + of Mat4F32: $list.mat4f32[] + of Mat4F64: $list.mat4f64[] + of TextureType: $list.texture[] diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/fonttypes.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/fonttypes.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,36 @@ +import std/tables +import std/unicode + +import ./vulkanapi +import ./imagetypes +import ./vector + +var FONTSAMPLER_SOFT* = Sampler( + magnification: VK_FILTER_LINEAR, + minification: VK_FILTER_LINEAR, + wrapModeS: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + wrapModeT: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + ) +var FONTSAMPLER_HARD* = Sampler( + magnification: VK_FILTER_NEAREST, + minification: VK_FILTER_NEAREST, + wrapModeS: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + wrapModeT: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + ) + + +type + GlyphInfo* = object + uvs*: array[4, Vec2f] + dimension*: Vec2f + topOffset*: float32 + leftOffset*: float32 + advance*: float32 + Font* = object + name*: string # used to reference fontAtlas will be referenced in shader + glyphs*: Table[Rune, GlyphInfo] + fontAtlas*: Texture + maxHeight*: int + kerning*: Table[(Rune, Rune), float32] + resolution*: float32 + fontscale*: float32 diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/gpu_types.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/gpu_types.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,400 @@ +import std/strformat +import std/tables + +import ./vulkanapi +import ./vector +import ./matrix +import ./imagetypes + +type + GPUType* = float32 | float64 | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | TVec2[int32] | TVec2[int64] | TVec3[int32] | TVec3[int64] | TVec4[int32] | TVec4[int64] | TVec2[uint32] | TVec2[uint64] | TVec3[uint32] | TVec3[uint64] | TVec4[uint32] | TVec4[uint64] | TVec2[float32] | TVec2[float64] | TVec3[float32] | TVec3[float64] | TVec4[float32] | TVec4[float64] | TMat2[float32] | TMat2[float64] | TMat23[float32] | TMat23[float64] | TMat32[float32] | TMat32[float64] | TMat3[float32] | TMat3[float64] | TMat34[float32] | TMat34[float64] | TMat43[float32] | TMat43[float64] | TMat4[float32] | TMat4[float64] | Texture + DataType* = enum + Float32 + Float64 + Int8 + Int16 + Int32 + Int64 + UInt8 + UInt16 + UInt32 + UInt64 + Vec2I32 + Vec2I64 + Vec3I32 + Vec3I64 + Vec4I32 + Vec4I64 + Vec2U32 + Vec2U64 + Vec3U32 + Vec3U64 + Vec4U32 + Vec4U64 + Vec2F32 + Vec2F64 + Vec3F32 + Vec3F64 + Vec4F32 + Vec4F64 + Mat2F32 + Mat2F64 + Mat23F32 + Mat23F64 + Mat32F32 + Mat32F64 + Mat3F32 + Mat3F64 + Mat34F32 + Mat34F64 + Mat43F32 + Mat43F64 + Mat4F32 + Mat4F64 + TextureType + MemoryPerformanceHint* = enum + PreferFastRead, PreferFastWrite + ShaderAttribute* = object + name*: string + theType*: DataType + arrayCount*: int + perInstance*: bool + noInterpolation: bool + memoryPerformanceHint*: MemoryPerformanceHint + +func vertexInputs*(attributes: seq[ShaderAttribute]): seq[ShaderAttribute] = + for attr in attributes: + if attr.perInstance == false: + result.add attr + +func instanceInputs*(attributes: seq[ShaderAttribute]): seq[ShaderAttribute] = + for attr in attributes: + if attr.perInstance == false: + result.add attr + +func numberOfVertexInputAttributeDescriptors*(theType: DataType): int = + case theType: + of Mat2F32, Mat2F64, Mat23F32, Mat23F64: 2 + of Mat32F32, Mat32F64, Mat3F32, Mat3F64, Mat34F32, Mat34F64: 3 + of Mat43F32, Mat43F64, Mat4F32, Mat4F64: 4 + else: 1 + +func size*(theType: DataType): int = + case theType: + of Float32: 4 + of Float64: 8 + of Int8: 1 + of Int16: 2 + of Int32: 4 + of Int64: 8 + of UInt8: 1 + of UInt16: 2 + of UInt32: 4 + of UInt64: 8 + of Vec2I32: 8 + of Vec2I64: 16 + of Vec3I32: 12 + of Vec3I64: 24 + of Vec4I32: 16 + of Vec4I64: 32 + of Vec2U32: 8 + of Vec2U64: 16 + of Vec3U32: 12 + of Vec3U64: 24 + of Vec4U32: 16 + of Vec4U64: 32 + of Vec2F32: 8 + of Vec2F64: 16 + of Vec3F32: 12 + of Vec3F64: 24 + of Vec4F32: 16 + of Vec4F64: 32 + of Mat2F32: 16 + of Mat2F64: 32 + of Mat23F32: 24 + of Mat23F64: 48 + of Mat32F32: 24 + of Mat32F64: 48 + of Mat3F32: 36 + of Mat3F64: 72 + of Mat34F32: 48 + of Mat34F64: 92 + of Mat43F32: 48 + of Mat43F64: 92 + of Mat4F32: 64 + of Mat4F64: 128 + of TextureType: 0 + +func size*(attribute: ShaderAttribute, perDescriptor=false): int = + if perDescriptor: + attribute.theType.size div attribute.theType.numberOfVertexInputAttributeDescriptors + else: + if attribute.arrayCount == 0: + attribute.theType.size + else: + attribute.theType.size * attribute.arrayCount + +func size*(theType: seq[ShaderAttribute]): int = + for attribute in theType: + result += attribute.size + +func getDataType*[T: GPUType|int|uint|float](): DataType = + when T is float32: Float32 + elif T is float64: Float64 + elif T is int8: Int8 + elif T is int16: Int16 + elif T is int32: Int32 + elif T is int64: Int64 + elif T is uint8: UInt8 + elif T is uint16: UInt16 + elif T is uint32: UInt32 + elif T is uint64: UInt64 + elif T is int and sizeof(int) == sizeof(int64): Int64 + elif T is int and sizeof(int) == sizeof(int32): Int32 + elif T is uint and sizeof(uint) == sizeof(uint64): UInt64 + elif T is uint and sizeof(uint) == sizeof(uint32): UInt32 + elif T is float and sizeof(float) == sizeof(float32): Float32 + elif T is float and sizeof(float) == sizeof(float64): Float64 + elif T is TVec2[int32]: Vec2I32 + elif T is TVec2[int64]: Vec2I64 + elif T is TVec3[int32]: Vec3I32 + elif T is TVec3[int64]: Vec3I64 + elif T is TVec4[int32]: Vec4I32 + elif T is TVec4[int64]: Vec4I64 + elif T is TVec2[uint32]: Vec2U32 + elif T is TVec2[uint64]: Vec2U64 + elif T is TVec3[uint32]: Vec3U32 + elif T is TVec3[uint64]: Vec3U64 + elif T is TVec4[uint32]: Vec4U32 + elif T is TVec4[uint64]: Vec4U64 + elif T is TVec2[float32]: Vec2F32 + elif T is TVec2[float64]: Vec2F64 + elif T is TVec3[float32]: Vec3F32 + elif T is TVec3[float64]: Vec3F64 + elif T is TVec4[float32]: Vec4F32 + elif T is TVec4[float64]: Vec4F64 + elif T is TMat2[float32]: Mat2F32 + elif T is TMat2[float64]: Mat2F64 + elif T is TMat23[float32]: Mat23F32 + elif T is TMat23[float64]: Mat23F64 + elif T is TMat32[float32]: Mat32F32 + elif T is TMat32[float64]: Mat32F64 + elif T is TMat3[float32]: Mat3F32 + elif T is TMat3[float64]: Mat3F64 + elif T is TMat34[float32]: Mat34F32 + elif T is TMat34[float64]: Mat34F64 + elif T is TMat43[float32]: Mat43F32 + elif T is TMat43[float64]: Mat43F64 + elif T is TMat4[float32]: Mat4F32 + elif T is TMat4[float64]: Mat4F64 + elif T is Texture: TextureType + else: + static: + raise newException(Exception, &"Unsupported data type for GPU data: {name(T)}" ) + +func attr*[T: GPUType]( + name: string, + perInstance=false, + arrayCount=0, + noInterpolation=false, + memoryPerformanceHint=PreferFastRead, +): auto = + ShaderAttribute( + name: name, + theType: getDataType[T](), + perInstance: perInstance, + arrayCount: arrayCount, + noInterpolation: noInterpolation, + memoryPerformanceHint: memoryPerformanceHint, + ) + +const TYPEMAP = { + Float32: VK_FORMAT_R32_SFLOAT, + Float64: VK_FORMAT_R64_SFLOAT, + Int8: VK_FORMAT_R8_SINT, + Int16: VK_FORMAT_R16_SINT, + Int32: VK_FORMAT_R32_SINT, + Int64: VK_FORMAT_R64_SINT, + UInt8: VK_FORMAT_R8_UINT, + UInt16: VK_FORMAT_R16_UINT, + UInt32: VK_FORMAT_R32_UINT, + UInt64: VK_FORMAT_R64_UINT, + Vec2I32: VK_FORMAT_R32G32_SINT, + Vec2I64: VK_FORMAT_R64G64_SINT, + Vec3I32: VK_FORMAT_R32G32B32_SINT, + Vec3I64: VK_FORMAT_R64G64B64_SINT, + Vec4I32: VK_FORMAT_R32G32B32A32_SINT, + Vec4I64: VK_FORMAT_R64G64B64A64_SINT, + Vec2U32: VK_FORMAT_R32G32_UINT, + Vec2U64: VK_FORMAT_R64G64_UINT, + Vec3U32: VK_FORMAT_R32G32B32_UINT, + Vec3U64: VK_FORMAT_R64G64B64_UINT, + Vec4U32: VK_FORMAT_R32G32B32A32_UINT, + Vec4U64: VK_FORMAT_R64G64B64A64_UINT, + Vec2F32: VK_FORMAT_R32G32_SFLOAT, + Vec2F64: VK_FORMAT_R64G64_SFLOAT, + Vec3F32: VK_FORMAT_R32G32B32_SFLOAT, + Vec3F64: VK_FORMAT_R64G64B64_SFLOAT, + Vec4F32: VK_FORMAT_R32G32B32A32_SFLOAT, + Vec4F64: VK_FORMAT_R64G64B64A64_SFLOAT, + Mat2F32: VK_FORMAT_R32G32_SFLOAT, + Mat2F64: VK_FORMAT_R64G64_SFLOAT, + Mat23F32: VK_FORMAT_R32G32B32_SFLOAT, + Mat23F64: VK_FORMAT_R64G64B64_SFLOAT, + Mat32F32: VK_FORMAT_R32G32_SFLOAT, + Mat32F64: VK_FORMAT_R64G64_SFLOAT, + Mat3F32: VK_FORMAT_R32G32B32_SFLOAT, + Mat3F64: VK_FORMAT_R64G64B64_SFLOAT, + Mat34F32: VK_FORMAT_R32G32B32A32_SFLOAT, + Mat34F64: VK_FORMAT_R64G64B64A64_SFLOAT, + Mat43F32: VK_FORMAT_R32G32B32_SFLOAT, + Mat43F64: VK_FORMAT_R64G64B64_SFLOAT, + Mat4F32: VK_FORMAT_R32G32B32A32_SFLOAT, + Mat4F64: VK_FORMAT_R64G64B64A64_SFLOAT, +}.toTable + +func getVkFormat*(theType: DataType): VkFormat = + TYPEMAP[theType] + +# from https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html +func nLocationSlots*(theType: DataType): int = + #[ + single location: + 16-bit scalar and vector types, and + 32-bit scalar and vector types, and + 64-bit scalar and 2-component vector types. + two locations + 64-bit three- and four-component vectors + ]# + case theType: + of Float32: 1 + of Float64: 1 + of Int8: 1 + of Int16: 1 + of Int32: 1 + of Int64: 1 + of UInt8: 1 + of UInt16: 1 + of UInt32: 1 + of UInt64: 1 + of Vec2I32: 1 + of Vec2I64: 1 + of Vec3I32: 1 + of Vec3I64: 2 + of Vec4I32: 1 + of Vec4I64: 2 + of Vec2U32: 1 + of Vec2U64: 1 + of Vec3U32: 1 + of Vec3U64: 2 + of Vec4U32: 1 + of Vec4U64: 2 + of Vec2F32: 1 + of Vec2F64: 1 + of Vec3F32: 1 + of Vec3F64: 2 + of Vec4F32: 1 + of Vec4F64: 2 + of Mat2F32: 1 + of Mat2F64: 1 + of Mat23F32: 1 + of Mat23F64: 2 + of Mat32F32: 1 + of Mat32F64: 1 + of Mat3F32: 1 + of Mat3F64: 2 + of Mat34F32: 1 + of Mat34F64: 2 + of Mat43F32: 1 + of Mat43F64: 2 + of Mat4F32: 1 + of Mat4F64: 2 + of TextureType: 1 + +func glslType*(theType: DataType): string = + # todo: likely not correct as we would need to enable some + # extensions somewhere (Vulkan/GLSL compiler?) to have + # everything work as intended. Or maybe the GPU driver does + # some automagic conversion stuf.. + case theType: + of Float32: "float" + of Float64: "double" + of Int8, Int16, Int32, Int64: "int" + of UInt8, UInt16, UInt32, UInt64: "uint" + of Vec2I32: "ivec2" + of Vec2I64: "ivec2" + of Vec3I32: "ivec3" + of Vec3I64: "ivec3" + of Vec4I32: "ivec4" + of Vec4I64: "ivec4" + of Vec2U32: "uvec2" + of Vec2U64: "uvec2" + of Vec3U32: "uvec3" + of Vec3U64: "uvec3" + of Vec4U32: "uvec4" + of Vec4U64: "uvec4" + of Vec2F32: "vec2" + of Vec2F64: "dvec2" + of Vec3F32: "vec3" + of Vec3F64: "dvec3" + of Vec4F32: "vec4" + of Vec4F64: "dvec4" + of Mat2F32: "mat2" + of Mat2F64: "dmat2" + of Mat23F32: "mat23" + of Mat23F64: "dmat23" + of Mat32F32: "mat32" + of Mat32F64: "dmat32" + of Mat3F32: "mat3" + of Mat3F64: "dmat3" + of Mat34F32: "mat34" + of Mat34F64: "dmat34" + of Mat43F32: "mat43" + of Mat43F64: "dmat43" + of Mat4F32: "mat4" + of Mat4F64: "dmat4" + of TextureType: "sampler2D" + +func glslInput*(group: openArray[ShaderAttribute]): seq[string] = + if group.len == 0: + return @[] + var i = 0 + for attribute in group: + assert attribute.arrayCount == 0, "arrays not supported for shader vertex attributes" + let flat = if attribute.noInterpolation: "flat " else: "" + result.add &"layout(location = {i}) {flat}in {attribute.theType.glslType} {attribute.name};" + for j in 0 ..< attribute.theType.numberOfVertexInputAttributeDescriptors: + i += attribute.theType.nLocationSlots + +func glslUniforms*(group: openArray[ShaderAttribute], blockName="Uniforms", binding: int): seq[string] = + if group.len == 0: + return @[] + # currently only a single uniform block supported, therefore binding = 0 + result.add(&"layout(std430, binding = {binding}) uniform T{blockName} {{") + for attribute in group: + var arrayDecl = "" + if attribute.arrayCount > 0: + arrayDecl = &"[{attribute.arrayCount}]" + result.add(&" {attribute.theType.glslType} {attribute.name}{arrayDecl};") + result.add(&"}} {blockName};") + +func glslSamplers*(group: openArray[ShaderAttribute], basebinding: int): seq[string] = + if group.len == 0: + return @[] + var thebinding = basebinding + for attribute in group: + var arrayDecl = "" + if attribute.arrayCount > 0: + arrayDecl = &"[{attribute.arrayCount}]" + result.add(&"layout(binding = {thebinding}) uniform {attribute.theType.glslType} {attribute.name}{arrayDecl};") + inc thebinding + +func glslOutput*(group: openArray[ShaderAttribute]): seq[string] = + if group.len == 0: + return @[] + var i = 0 + for attribute in group: + assert attribute.arrayCount == 0, "arrays not supported for outputs" + let flat = if attribute.noInterpolation: "flat " else: "" + result.add &"layout(location = {i}) {flat}out {attribute.theType.glslType} {attribute.name};" + i += 1 diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/imagetypes.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/imagetypes.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,74 @@ +import std/strformat + +import ./vulkanapi +import ./vector + +type + Pixel* = array[4, uint8] + ImageObject* = object + width*: int + height*: int + imagedata*: seq[Pixel] + Sampler* = object + magnification*: VkFilter = VK_FILTER_LINEAR + minification*: VkFilter = VK_FILTER_LINEAR + wrapModeS*: VkSamplerAddressMode = VK_SAMPLER_ADDRESS_MODE_REPEAT + wrapModeT*: VkSamplerAddressMode = VK_SAMPLER_ADDRESS_MODE_REPEAT + + Image* = ref ImageObject + Texture* = object + name*: string + image*: Image + sampler*: Sampler + +converter toRGBA*(p: Pixel): Vec4f = + newVec4f(float32(p[0]) / 255'f32, float32(p[1]) / 255'f32, float32(p[2]) / 255'f32, float32(p[3]) / 255'f32) + +proc `$`*(image: Image): string = + &"{image.width}x{image.height}" + +proc `$`*(texture: Texture): string = + &"{texture.name} {texture.image}" + +proc `[]`*(image: Image, x, y: int): Pixel = + assert x < image.width + assert y < image.height + + image[].imagedata[y * image.width + x] + +proc `[]=`*(image: var Image, x, y: int, value: Pixel) = + assert x < image.width + assert y < image.height + + image[].imagedata[y * image.width + x] = value + +const EMPTYPIXEL = [0'u8, 0'u8, 0'u8, 0'u8] +proc newImage*(width, height: int, imagedata: seq[Pixel] = @[], fill=EMPTYPIXEL): Image = + assert width > 0 and height > 0 + assert imagedata.len == width * height or imagedata.len == 0 + + result = new Image + result.imagedata = (if imagedata.len == 0: newSeq[Pixel](width * height) else: imagedata) + assert width * height == result.imagedata.len + + result.width = width + result.height = height + if fill != EMPTYPIXEL: + for y in 0 ..< height: + for x in 0 ..< width: + result[x, y] = fill + +let INVALID_TEXTURE* = Texture(name: "Invalid texture", image: newImage(1, 1, @[[255'u8, 0'u8, 255'u8, 255'u8]]), sampler: Sampler( + magnification: VK_FILTER_NEAREST, + minification: VK_FILTER_NEAREST, + wrapModeS: VK_SAMPLER_ADDRESS_MODE_REPEAT, + wrapModeT: VK_SAMPLER_ADDRESS_MODE_REPEAT, + ) +) +let EMPTY_TEXTURE* = Texture(name: "Empty texture", image: newImage(1, 1, @[[255'u8, 255'u8, 255'u8, 255'u8]]), sampler: Sampler( + magnification: VK_FILTER_NEAREST, + minification: VK_FILTER_NEAREST, + wrapModeS: VK_SAMPLER_ADDRESS_MODE_REPEAT, + wrapModeT: VK_SAMPLER_ADDRESS_MODE_REPEAT, + ) +) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/matrix.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/matrix.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,477 @@ +import std/math +import std/macros +import std/random +import std/strutils +import std/strformat +import std/typetraits + +import ./vector + +export math + +type + # layout is row-first + # having an object instead of directly aliasing the array seems a bit ugly at + # first, but is necessary to be able to work correctly with distinguished + # types (i.e. TMat23 and TMat32 would be an alias for the same type array[6, T] + # which prevents the type system from identifying the correct type at times) + # + # Though, great news is that objects have zero overhead! + TMat2*[T: SomeNumber] = object + data*: array[4, T] + TMat23*[T: SomeNumber] = object + data*: array[6, T] + TMat32*[T: SomeNumber] = object + data*: array[6, T] + TMat3*[T: SomeNumber] = object + data*: array[9, T] + TMat34*[T: SomeNumber] = object + data*: array[12, T] + TMat43*[T: SomeNumber] = object + data*: array[12, T] + TMat4*[T: SomeNumber] = object + data*: array[16, T] + TMat* = TMat2|TMat3|TMat4|TMat23|TMat32|TMat34|TMat43 + Mat2* = TMat2[float32] + Mat23* = TMat23[float32] + Mat32* = TMat32[float32] + Mat3* = TMat3[float32] + Mat34* = TMat34[float32] + Mat43* = TMat43[float32] + Mat4* = TMat4[float32] + +func unit2[T: SomeNumber](): auto {.compiletime.} = TMat2[T](data:[ + T(1), T(0), + T(0), T(1), +]) +func unit3[T: SomeNumber](): auto {.compiletime.} = TMat3[T](data:[ + T(1), T(0), T(0), + T(0), T(1), T(0), + T(0), T(0), T(1), +]) +func unit4[T: SomeNumber](): auto {.compiletime.} = TMat4[T](data: [ + T(1), T(0), T(0), T(0), + T(0), T(1), T(0), T(0), + T(0), T(0), T(1), T(0), + T(0), T(0), T(0), T(1), +]) + +# generates constants: Unit +# Also for Y, Z, R, G, B +# not sure if this is necessary or even a good idea... +macro generateAllConsts() = + result = newStmtList() + for theType in ["int", "int8", "int16", "int32", "int64", "float", "float32", "float64"]: + var typename = theType[0 .. 0] + if theType[^2].isDigit: + typename = typename & theType[^2] + if theType[^1].isDigit: + typename = typename & theType[^1] + result.add(newConstStmt( + postfix(ident("Unit2" & typename), "*"), + newCall(nnkBracketExpr.newTree(ident("unit2"), ident(theType))) + )) + result.add(newConstStmt( + postfix(ident("Unit3" & typename), "*"), + newCall(nnkBracketExpr.newTree(ident("unit3"), ident(theType))) + )) + result.add(newConstStmt( + postfix(ident("Unit4" & typename), "*"), + newCall(nnkBracketExpr.newTree(ident("unit4"), ident(theType))) + )) + +generateAllConsts() + +const Unit2* = unit2[float32]() +const Unit3* = unit3[float32]() +const Unit4* = unit4[float32]() + +template rowCount*(m: typedesc): int = + when m is TMat2: 2 + elif m is TMat23: 2 + elif m is TMat32: 3 + elif m is TMat3: 3 + elif m is TMat34: 3 + elif m is TMat43: 4 + elif m is TMat4: 4 +template columnCount*(m: typedesc): int = + when m is TMat2: 2 + elif m is TMat23: 3 + elif m is TMat32: 2 + elif m is TMat3: 3 + elif m is TMat34: 4 + elif m is TMat43: 3 + elif m is TMat4: 4 +template matlen*(m: typedesc): int = + when m is TMat2: 4 + elif m is TMat23: 6 + elif m is TMat32: 6 + elif m is TMat3: 9 + elif m is TMat34: 12 + elif m is TMat43: 12 + elif m is TMat4: 16 + + +func toString[T](value: T): string = + var + strvalues: seq[string] + maxwidth = 0 + + for n in value.data: + let strval = &"{n:.2}" + strvalues.add(strval) + if strval.len > maxwidth: + maxwidth = strval.len + + for i in 0 ..< strvalues.len: + let filler = " ".repeat(maxwidth - strvalues[i].len) + if i mod T.columnCount == T.columnCount - 1: + result &= filler & strvalues[i] & "\n" + else: + if i mod T.columnCount == 0: + result &= " " + result &= filler & strvalues[i] & " " + result = $T & "\n" & result + +func `$`*(v: TMat2[SomeNumber]): string = toString[TMat2[SomeNumber]](v) +func `$`*(v: TMat23[SomeNumber]): string = toString[TMat23[SomeNumber]](v) +func `$`*(v: TMat32[SomeNumber]): string = toString[TMat32[SomeNumber]](v) +func `$`*(v: TMat3[SomeNumber]): string = toString[TMat3[SomeNumber]](v) +func `$`*(v: TMat34[SomeNumber]): string = toString[TMat34[SomeNumber]](v) +func `$`*(v: TMat43[SomeNumber]): string = toString[TMat43[SomeNumber]](v) +func `$`*(v: TMat4[SomeNumber]): string = toString[TMat4[SomeNumber]](v) + +func `[]`*[T: TMat](m: T, row, col: int): auto = m.data[col + row * T.columnCount] +func `[]=`*[T: TMat, U](m: var T, row, col: int, value: U) = m.data[col + row * T.columnCount] = value +func `[]`*[T: TMat](m: T, i: int): auto = m.data[i] +func `[]=`*[T: TMat, U](m: var T, i: int, value: U) = m.data[i] = value + +func row*[T: TMat2](m: T, i: 0..1): auto = TVec2([m[i, 0], m[i, 1]]) +func row*[T: TMat32](m: T, i: 0..2): auto = TVec2([m[i, 0], m[i, 1]]) +func row*[T: TMat23](m: T, i: 0..1): auto = TVec3([m[i, 0], m[i, 1], m[i, 2]]) +func row*[T: TMat3](m: T, i: 0..2): auto = TVec3([m[i, 0], m[i, 1], m[i, 2]]) +func row*[T: TMat43](m: T, i: 0..3): auto = TVec3([m[i, 0], m[i, 1], m[i, 2]]) +func row*[T: TMat34](m: T, i: 0..2): auto = TVec4([m[i, 0], m[i, 1], m[i, 2], m[i, 3]]) +func row*[T: TMat4](m: T, i: 0..3): auto = TVec4([m[i, 0], m[i, 1], m[i, 2], m[i, 3]]) + +func col*[T: TMat2](m: T, i: 0..1): auto = TVec2([m[0, i], m[1, i]]) +func col*[T: TMat23](m: T, i: 0..2): auto = TVec2([m[0, i], m[1, i]]) +func col*[T: TMat32](m: T, i: 0..1): auto = TVec3([m[0, i], m[1, i], m[2, i]]) +func col*[T: TMat3](m: T, i: 0..2): auto = TVec3([m[0, i], m[1, i], m[2, i]]) +func col*[T: TMat34](m: T, i: 0..3): auto = TVec3([m[0, i], m[1, i], m[2, i]]) +func col*[T: TMat43](m: T, i: 0..2): auto = TVec4([m[0, i], m[1, i], m[2, i], m[3, i]]) +func col*[T: TMat4](m: T, i: 0..3): auto = TVec4([m[0, i], m[1, i], m[2, i], m[3, i]]) + +proc createMatMatMultiplicationOperator(leftType: typedesc, rightType: typedesc, outType: typedesc): NimNode = + var data = nnkBracket.newTree() + for i in 0 ..< rowCount(leftType): + for j in 0 ..< rightType.columnCount: + data.add(newCall( + ident("sum"), + infix( + newCall(newDotExpr(ident("a"), ident("row")), newLit(i)), + "*", + newCall(newDotExpr(ident("b"), ident("col")), newLit(j)) + ) + )) + + return newProc( + postfix(nnkAccQuoted.newTree(ident("*")), "*"), + params=[ + ident("auto"), + newIdentDefs(ident("a"), ident(leftType.name)), + newIdentDefs(ident("b"), ident(rightType.name)) + ], + body=nnkObjConstr.newTree(ident(outType.name), nnkExprColonExpr.newTree(ident("data"), data)), + procType=nnkFuncDef, + ) + +proc createMatMatAdditionOperator(theType: typedesc): NimNode = + var data = nnkBracket.newTree() + for i in 0 ..< matlen(theType): + data.add( + infix( + nnkBracketExpr.newTree(ident("a"), newLit(i)), + "+", + nnkBracketExpr.newTree(ident("b"), newLit(i)), + )) + + return newProc( + postfix(nnkAccQuoted.newTree(ident("+")), "*"), + params=[ + ident("auto"), + newIdentDefs(ident("a"), ident(theType.name)), + newIdentDefs(ident("b"), ident(theType.name)) + ], + body=nnkObjConstr.newTree(ident(theType.name), nnkExprColonExpr.newTree(ident("data"), data)), + procType=nnkFuncDef, + ) + +proc createVecMatMultiplicationOperator(matType: typedesc, vecType: typedesc): NimNode = + var data = nnkBracket.newTree() + for i in 0 ..< matType.rowCount: + data.add(newCall( + ident("sum"), + infix( + ident("v"), + "*", + newCall(newDotExpr(ident("m"), ident("row")), newLit(i)) + ) + )) + + let resultVec = newCall( + nnkBracketExpr.newTree(ident(vecType.name), ident("T")), + data, + ) + let name = postfix(nnkAccQuoted.newTree(ident("*")), "*") + let genericParams = nnkGenericParams.newTree(nnkIdentDefs.newTree(ident("T"), ident("SomeNumber"), newEmptyNode())) + let formalParams = nnkFormalParams.newTree( + ident("auto"), + newIdentDefs(ident("m"), nnkBracketExpr.newTree(ident(matType.name), ident("T"))), + newIdentDefs(ident("v"), nnkBracketExpr.newTree(ident(vecType.name), ident("T"))), + ) + + return nnkFuncDef.newTree( + name, + newEmptyNode(), + genericParams, + formalParams, + newEmptyNode(), + newEmptyNode(), + resultVec + ) + + +proc createMatScalarOperator(matType: typedesc, op: string): NimNode = + result = newStmtList() + + var data = nnkBracket.newTree() + for i in 0 ..< matType.rowCount * matType.columnCount: + data.add(infix(nnkBracketExpr.newTree(newDotExpr(ident("a"), ident("data")), newLit(i)), op, ident("b"))) + result.add(newProc( + postfix(nnkAccQuoted.newTree(ident(op)), "*"), + params=[ + ident("auto"), + newIdentDefs(ident("a"), ident(matType.name)), + newIdentDefs(ident("b"), ident("SomeNumber")), + ], + body=nnkObjConstr.newTree(ident(matType.name), nnkExprColonExpr.newTree(ident("data"), data)), + procType=nnkFuncDef, + )) + result.add(newProc( + postfix(nnkAccQuoted.newTree(ident(op)), "*"), + params=[ + ident("auto"), + newIdentDefs(ident("b"), ident("SomeNumber")), + newIdentDefs(ident("a"), ident(matType.name)), + ], + body=nnkObjConstr.newTree(ident(matType.name), nnkExprColonExpr.newTree(ident("data"), data)), + procType=nnkFuncDef, + )) + if op == "-": + var data2 = nnkBracket.newTree() + for i in 0 ..< matType.rowCount * matType.columnCount: + data2.add(prefix(nnkBracketExpr.newTree(newDotExpr(ident("a"), ident("data")), newLit(i)), op)) + result.add(newProc( + postfix(nnkAccQuoted.newTree(ident(op)), "*"), + params=[ + ident("auto"), + newIdentDefs(ident("a"), ident(matType.name)), + ], + body=nnkObjConstr.newTree(ident(matType.name), nnkExprColonExpr.newTree(ident("data"), data2)), + procType=nnkFuncDef, + )) + +macro createAllMultiplicationOperators() = + result = newStmtList() + + for op in ["+", "-", "*", "/"]: + result.add(createMatScalarOperator(TMat2, op)) + result.add(createMatScalarOperator(TMat23, op)) + result.add(createMatScalarOperator(TMat32, op)) + result.add(createMatScalarOperator(TMat3, op)) + result.add(createMatScalarOperator(TMat34, op)) + result.add(createMatScalarOperator(TMat43, op)) + result.add(createMatScalarOperator(TMat4, op)) + + result.add(createMatMatMultiplicationOperator(TMat2, TMat2, TMat2)) + result.add(createMatMatMultiplicationOperator(TMat2, TMat23, TMat23)) + result.add(createMatMatMultiplicationOperator(TMat23, TMat32, TMat2)) + result.add(createMatMatMultiplicationOperator(TMat23, TMat3, TMat23)) + result.add(createMatMatMultiplicationOperator(TMat32, TMat2, TMat32)) + result.add(createMatMatMultiplicationOperator(TMat32, TMat23, TMat3)) + result.add(createMatMatMultiplicationOperator(TMat3, TMat32, TMat32)) + result.add(createMatMatMultiplicationOperator(TMat3, TMat3, TMat3)) + result.add(createMatMatMultiplicationOperator(TMat3, TMat34, TMat34)) + result.add(createMatMatMultiplicationOperator(TMat43, TMat3, TMat43)) + result.add(createMatMatMultiplicationOperator(TMat43, TMat34, TMat4)) + result.add(createMatMatMultiplicationOperator(TMat4, TMat43, TMat43)) + result.add(createMatMatMultiplicationOperator(TMat4, TMat4, TMat4)) + + result.add(createMatMatAdditionOperator(TMat2)) + result.add(createMatMatAdditionOperator(TMat23)) + result.add(createMatMatAdditionOperator(TMat32)) + result.add(createMatMatAdditionOperator(TMat3)) + result.add(createMatMatAdditionOperator(TMat34)) + result.add(createMatMatAdditionOperator(TMat43)) + result.add(createMatMatAdditionOperator(TMat4)) + + result.add(createVecMatMultiplicationOperator(TMat2, TVec2)) + result.add(createVecMatMultiplicationOperator(TMat3, TVec3)) + result.add(createVecMatMultiplicationOperator(TMat4, TVec4)) + +createAllMultiplicationOperators() + +func `*`*(mat: Mat4, vec: Vec3f): Vec3f = + (mat * vec.toVec4(1)).toVec3 + +func transposed*[T](m: TMat2[T]): TMat2[T] = TMat2[T](data: [ + m[0, 0], m[1, 0], + m[0, 1], m[1, 1], +]) +func transposed*[T](m: TMat23[T]): TMat32[T] = TMat32[T](data: [ + m[0, 0], m[1, 0], + m[0, 1], m[1, 1], + m[0, 2], m[1, 2], +]) +func transposed*[T](m: TMat32[T]): TMat23[T] = TMat23[T](data: [ + m[0, 0], m[1, 0], m[2, 0], + m[0, 1], m[1, 1], m[2, 1], +]) +func transposed*[T](m: TMat3[T]): TMat3[T] = TMat3[T](data: [ + m[0, 0], m[1, 0], m[2, 0], + m[0, 1], m[1, 1], m[2, 1], + m[0, 2], m[1, 2], m[2, 2], +]) +func transposed*[T](m: TMat43[T]): TMat34[T] = TMat34[T](data: [ + m[0, 0], m[1, 0], m[2, 0], m[3, 0], + m[0, 1], m[1, 1], m[2, 1], m[3, 1], + m[0, 2], m[1, 2], m[2, 2], m[3, 2], +]) +func transposed*[T](m: TMat34[T]): TMat43[T] = TMat43[T](data: [ + m[0, 0], m[1, 0], m[2, 0], + m[0, 1], m[1, 1], m[2, 1], + m[0, 2], m[1, 2], m[2, 2], + m[0, 3], m[1, 3], m[2, 3], +]) +func transposed*[T](m: TMat4[T]): TMat4[T] = TMat4[T](data: [ + m[0, 0], m[1, 0], m[2, 0], m[3, 0], + m[0, 1], m[1, 1], m[2, 1], m[3, 1], + m[0, 2], m[1, 2], m[2, 2], m[3, 2], + m[0, 3], m[1, 3], m[2, 3], m[3, 3], +]) + +func translate2d*[T](x, y: T): TMat3[T] = TMat3[T](data: [ + T(1), T(0), x, + T(0), T(1), y, + T(0), T(0), T(1), +]) +func scale2d*[T](sx, sy: T): TMat3[T] = TMat3[T](data: [ + sx, T(0), T(0), + T(0), sy, T(0), + T(0), T(0), T(1), +]) +func rotate2d*[T](angle: T): TMat3[T] = TMat3[T](data: [ + cos(angle), -sin(angle), T(0), + sin(angle), cos(angle), T(0), + T(0), T(0), T(1), +]) +func translate*(x=0'f32, y=0'f32, z=0'f32): TMat4[float32] = Mat4(data: [ + 1'f32, 0'f32, 0'f32, x, + 0'f32, 1'f32, 0'f32, y, + 0'f32, 0'f32, 1'f32, z, + 0'f32, 0'f32, 0'f32, 1'f32, +]) +func translate*[T: TVec3](v: T): TMat4[float32] = translate(v[0], v[1], v[2]) +func scale*(x=1'f32, y=1'f32, z=1'f32): Mat4 = Mat4(data: [ + x, 0'f32, 0'f32, 0'f32, + 0'f32, y, 0'f32, 0'f32, + 0'f32, 0'f32, z, 0'f32, + 0'f32, 0'f32, 0'f32, 1'f32, +]) +func scale*[T: TVec3](v: T): TMat4[float32] = scale(v[0], v[1], v[2]) +func rotate*(angle: float32, a: Vec3f): Mat4 = + let + cosa = cos(angle) + sina = sin(angle) + x = a[0] + y = a[1] + z = a[2] + Mat4(data: [ + x * x * (1 - cosa) + cosa, y * x * (1 - cosa) - z * sina, z * x * (1 - cosa) + y * sina, 0'f32, + x * y * (1 - cosa) + z * sina, y * y * (1 - cosa) + cosa, z * y * (1 - cosa) - x * sina, 0'f32, + x * z * (1 - cosa) - y * sina, y * z * (1 - cosa) + x * sina, z * z * (1 - cosa) + cosa, 0'f32, + 0'f32, 0'f32, 0'f32, 1'f32, + ]) + +func asMat3(m: Mat4): auto = + Mat3(data: [ + m[0, 0], m[0, 1], m[0, 2], + m[1, 0], m[1, 1], m[1, 2], + m[2, 0], m[2, 1], m[2, 2], + ]) + + +func inversed*(m: Mat4): Mat4 = + var m3 = m.asMat3.transposed + m3[0, 0] = 1'f32 / m3[0, 0] + m3[1, 1] = 1'f32 / m3[1, 1] + m3[2, 2] = 1'f32 / m3[2, 2] + let col3 = -(m3 * m.col(3).xyz) + return Mat4(data: [ + m3[0, 0], m3[0, 1], m3[0, 2], col3.x, + m3[1, 0], m3[1, 1], m3[1, 2], col3.y, + m3[2, 0], m3[2, 1], m3[2, 2], col3.z, + 0, 0, 0, 1, + ]) + + +# call e.g. TMat32[int]().randomized() to get a random matrix +template makeRandomInit(mattype: typedesc) = + proc randomized*[T: SomeInteger](m: mattype[T]): mattype[T] = + for i in 0 ..< result.data.len: + result.data[i] = rand(low(typeof(m.data[0])) .. high(typeof(m.data[0]))) + proc randomized*[T: SomeFloat](m: mattype[T]): mattype[T] = + for i in 0 ..< result.data.len: + result.data[i] = rand(T(1.0)) + +makeRandomInit(TMat2) +makeRandomInit(TMat23) +makeRandomInit(TMat32) +makeRandomInit(TMat3) +makeRandomInit(TMat34) +makeRandomInit(TMat43) +makeRandomInit(TMat4) + +func perspective*(fovy, aspect, zNear, zFar: float32): Mat4 = + let tanHalfFovy = tan(fovy / 2) + return Mat4(data:[ + 1 / (aspect * tanHalfFovy), 0, 0, 0, + 0, 1 / tanHalfFovy, 0, 0, + 0, 0, zFar / (zFar - zNear), -(zFar * zNear) / (zFar - zNear), + 0, 0, 1, 1, + ]) + +func ortho*(left, right, top, bottom, zNear, zFar: float32): Mat4 = + Mat4(data:[ + 2 / (right - left), 0, 0, -(right + left) / (right - left), + 0, 2 / (bottom - top), 0, -(bottom + top) / (bottom - top), + 0, 0, 1 / (zFar - zNear), -zNear / (zFar - zNear), + 0, 0, 1, 1, + ]) + +# create an orthographic perspective that will map from -1 .. 1 on all axis and keep a 1:1 aspect ratio +# the smaller dimension (width or height) will always be 1 and the larger dimension will be larger, to keep the ratio +func orthoWindowAspect*(windowAspect: float32): Mat4 = + if windowAspect > 1: + let space = 2 * (windowAspect - 1) / 2 + ortho(-1, 1, -1 - space, 1 + space, 0, 1) + else: + let space = 2 * (1 / windowAspect - 1) / 2 + ortho(-1 - space, 1 + space, -1, 1, 0, 1) + +func position*(mat: Mat4): Vec3f = + mat.col(3).toVec3 + +func scaling*(mat: Mat4): Vec3f = + newVec3f(mat[0, 0], mat[1, 1], mat[2, 2]) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/utils.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/utils.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,23 @@ +import std/typetraits +import std/strutils +import std/strformat + +func cleanString*(str: openArray[char]): string = + for i in 0 ..< len(str): + if str[i] == char(0): + result = join(str[0 ..< i]) + break + +func toCPointer*[T](list: seq[T]): ptr T = + if list.len > 0: addr(list[0]) else: nil + +proc staticExecChecked*(command: string, input = ""): string {.compileTime.} = + let (output, exitcode) = gorgeEx( + command = command, + input = input) + if exitcode != 0: + raise newException(Exception, &"Running '{command}' produced exit code: {exitcode}" & output) + return output + +func size*[T: seq](list: T): uint64 = + uint64(list.len * sizeof(get(genericParams(typeof(list)), 0))) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/vector.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/vector.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,326 @@ +import std/random +import std/math +import std/strutils +import std/macros +import std/typetraits +import std/tables + +import ./vulkanapi + +type + TVec2*[T: SomeNumber] = array[2, T] + TVec3*[T: SomeNumber] = array[3, T] + TVec4*[T: SomeNumber] = array[4, T] + TVec* = TVec2|TVec3|TVec4 + Vec2f* = TVec2[float32] + Vec3f* = TVec3[float32] + Vec4f* = TVec4[float32] + Vec2i* = TVec2[int32] + Vec3i* = TVec3[int32] + Vec4i* = TVec4[int32] + Vec2u* = TVec2[uint32] + Vec3u* = TVec3[uint32] + Vec4u* = TVec4[uint32] + +converter toVec2*[T: SomeNumber](orig: TVec3[T]|TVec4[T]): TVec2[T] = + TVec2[T]([orig[0], orig[1]]) +converter toVec3*[T: SomeNumber](orig: TVec4[T]): TVec3[T] = + TVec3[T]([orig[0], orig[1], orig[2]]) + +func toVec4*[T: SomeNumber](orig: TVec3[T], value: T = default(T)): TVec4[T] = + TVec4[T]([orig[0], orig[1], orig[2], value]) +func toVec3*[T: SomeNumber](orig: TVec2[T], value: T = default(T)): TVec3[T] = + TVec3[T]([orig[0], orig[1], value]) + +# define some often used constants +func ConstOne2[T: SomeNumber](): auto {.compiletime.} = TVec2[T]([T(1), T(1)]) +func ConstOne3[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(1), T(1), T(1)]) +func ConstOne4[T: SomeNumber](): auto {.compiletime.} = TVec4[T]([T(1), T(1), T(1), T(1)]) +func ConstX[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(1), T(0), T(0)]) +func ConstY[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(0), T(1), T(0)]) +func ConstZ[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(0), T(0), T(1)]) +func ConstR[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(1), T(0), T(0)]) +func ConstG[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(0), T(1), T(0)]) +func ConstB[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(0), T(0), T(1)]) + +func newVec2f*(x=0'f32, y=0'f32): auto = + Vec2f([x, y]) +func newVec3f*(x=0'f32, y=0'f32, z=0'f32): auto = + Vec3f([x, y, z]) +func newVec4f*(x=0'f32, y=0'f32, z=0'f32, a=0'f32): auto = + Vec4f([x, y, z, a]) +func newVec2i*(x=0'i32, y=0'i32): auto = + Vec2i([x, y]) +func newVec3i*(x=0'i32, y=0'i32, z=0'i32): auto = + Vec3i([x, y, z]) +func newVec4i*(x=0'i32, y=0'i32, z=0'i32, a=0'i32): auto = + Vec4i([x, y, z, a]) +func newVec2u*(x=0'u32, y=0'u32): auto = + Vec2u([x, y]) +func newVec3u*(x=0'u32, y=0'u32, z=0'u32): auto = + Vec3u([x, y, z]) +func newVec4u*(x=0'u32, y=0'u32, z=0'u32, a=0'u32): auto = + Vec4u([x, y, z, a]) + +# generates constants: Xf, Xf32, Xf64, Xi, Xi8, Xi16, Xi32, Xi64 +# Also for Y, Z, R, G, B and One +# not sure if this is necessary or even a good idea... +macro generateAllConsts() = + result = newStmtList() + for component in ["X", "Y", "Z", "R", "G", "B", "One2", "One3", "One4"]: + for theType in ["int", "int8", "int16", "int32", "int64", "float", "float32", "float64"]: + var typename = theType[0 .. 0] + if theType[^2].isDigit: + typename = typename & theType[^2] + if theType[^1].isDigit: + typename = typename & theType[^1] + result.add( + newConstStmt( + postfix(ident(component & typename), "*"), + newCall(nnkBracketExpr.newTree(ident("Const" & component), ident(theType))) + ) + ) + +generateAllConsts() + +const X* = ConstX[float32]() +const Y* = ConstY[float32]() +const Z* = ConstZ[float32]() +const One2* = ConstOne2[float32]() +const One3* = ConstOne3[float32]() +const One4* = ConstOne4[float32]() + +func newVec2*[T](x, y: T): auto = TVec2([x, y]) +func newVec3*[T](x, y, z: T): auto = TVec3([x, y, z]) +func newVec4*[T](x, y, z, w: T): auto = TVec4([x, y, z, w]) + +func to*[T](v: TVec2): auto = TVec2([T(v[0]), T(v[1])]) +func to*[T](v: TVec3): auto = TVec3([T(v[0]), T(v[1]), T(v[2])]) +func to*[T](v: TVec4): auto = TVec4([T(v[0]), T(v[1]), T(v[2]), T(v[3])]) + +func toString[T](value: T): string = + var items: seq[string] + for item in value: + items.add($item) + $T & "(" & join(items, " ") & ")" + +func `$`*(v: TVec2[SomeNumber]): string = toString[TVec2[SomeNumber]](v) +func `$`*(v: TVec3[SomeNumber]): string = toString[TVec3[SomeNumber]](v) +func `$`*(v: TVec4[SomeNumber]): string = toString[TVec4[SomeNumber]](v) + +func length*(vec: TVec2[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[1]) +func length*(vec: TVec2[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[ + 1] * vec[1])) +func length*(vec: TVec3[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[ + 1] + vec[2] * vec[2]) +func length*(vec: TVec3[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[ + 1] * vec[1] + vec[2] * vec[2])) +func length*(vec: TVec4[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[ + 1] + vec[2] * vec[2] + vec[3] * vec[3]) +func length*(vec: TVec4[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[ + 1] * vec[1] + vec[2] * vec[2] + vec[3] * vec[3])) + +func normalized*[T: SomeFloat](vec: TVec2[T]): auto = + let l = vec.length + if l == 0: vec + else: TVec2[T]([vec[0] / l, vec[1] / l]) +func normalized*[T: SomeFloat](vec: TVec3[T]): auto = + let l = vec.length + if l == 0: return vec + else: TVec3[T]([vec[0] / l, vec[1] / l, vec[2] / l]) +func normalized*[T: SomeFloat](vec: TVec4[T]): auto = + let l = vec.length + if l == 0: return vec + else: TVec4[T]([vec[0] / l, vec[1] / l, vec[2] / l, vec[3] / l]) + +# scalar operations +func `+`*(a: TVec2, b: SomeNumber): auto = TVec2([a[0] + b, a[1] + b]) +func `+`*(a: TVec3, b: SomeNumber): auto = TVec3([a[0] + b, a[1] + b, a[2] + b]) +func `+`*(a: TVec4, b: SomeNumber): auto = TVec4([a[0] + b, a[1] + b, a[2] + b, + a[3] + b]) +func `-`*(a: TVec2, b: SomeNumber): auto = TVec2([a[0] - b, a[1] - b]) +func `-`*(a: TVec3, b: SomeNumber): auto = TVec3([a[0] - b, a[1] - b, a[2] - b]) +func `-`*(a: TVec4, b: SomeNumber): auto = TVec4([a[0] - b, a[1] - b, a[2] - b, + a[3] - b]) +func `*`*(a: TVec2, b: SomeNumber): auto = TVec2([a[0] * b, a[1] * b]) +func `*`*(a: TVec3, b: SomeNumber): auto = TVec3([a[0] * b, a[1] * b, a[2] * b]) +func `*`*(a: TVec4, b: SomeNumber): auto = TVec4([a[0] * b, a[1] * b, a[2] * b, + a[3] * b]) +func `/`*[T: SomeInteger](a: TVec2[T], b: SomeInteger): auto = TVec2([a[ + 0] div b, a[1] div b]) +func `/`*[T: SomeFloat](a: TVec2[T], b: SomeFloat): auto = TVec2([a[0] / b, a[1] / b]) +func `/`*[T: SomeInteger](a: TVec3[T], b: SomeInteger): auto = TVec3([a[ + 0] div b, a[1] div b, a[2] div b]) +func `/`*[T: SomeFloat](a: TVec3[T], b: SomeFloat): auto = TVec3([a[0] / b, a[ + 1] / b, a[2] / b]) +func `/`*[T: SomeInteger](a: TVec4[T], b: SomeInteger): auto = TVec4([a[ + 0] div b, a[1] div b, a[2] div b, a[3] div b]) +func `/`*[T: SomeFloat](a: TVec4[T], b: SomeFloat): auto = TVec4([a[0] / b, a[ + 1] / b, a[2] / b, a[3] / b]) + +func `+`*(a: SomeNumber, b: TVec2): auto = TVec2([a + b[0], a + b[1]]) +func `+`*(a: SomeNumber, b: TVec3): auto = TVec3([a + b[0], a + b[1], a + b[2]]) +func `+`*(a: SomeNumber, b: TVec4): auto = TVec4([a + b[0], a + b[1], a + b[2], + a + b[3]]) +func `-`*(a: SomeNumber, b: TVec2): auto = TVec2([a - b[0], a - b[1]]) +func `-`*(a: SomeNumber, b: TVec3): auto = TVec3([a - b[0], a - b[1], a - b[2]]) +func `-`*(a: SomeNumber, b: TVec4): auto = TVec4([a - b[0], a - b[1], a - b[2], + a - b[3]]) +func `*`*(a: SomeNumber, b: TVec2): auto = TVec2([a * b[0], a * b[1]]) +func `*`*(a: SomeNumber, b: TVec3): auto = TVec3([a * b[0], a * b[1], a * b[2]]) +func `*`*(a: SomeNumber, b: TVec4): auto = TVec4([a * b[0], a * b[1], a * b[2], + a * b[3]]) +func `/`*[T: SomeInteger](a: SomeInteger, b: TVec2[T]): auto = TVec2([a div b[ + 0], a div b[1]]) +func `/`*[T: SomeFloat](a: SomeFloat, b: TVec2[T]): auto = TVec2([a / b[0], a / b[1]]) +func `/`*[T: SomeInteger](a: SomeInteger, b: TVec3[T]): auto = TVec3([a div b[ + 0], a div b[1], a div b[2]]) +func `/`*[T: SomeFloat](a: SomeFloat, b: TVec3[T]): auto = TVec3([a / b[0], a / + b[1], a / b[2]]) +func `/`*[T: SomeInteger](a: SomeInteger, b: TVec4[T]): auto = TVec4([a div b[ + 0], a div b[1], a div b[2], a div b[3]]) +func `/`*[T: SomeFloat](a: SomeFloat, b: TVec4[T]): auto = TVec4([a / b[0], a / + b[1], a / b[2], a / b[3]]) + +# compontent-wise operations +func `+`*(a, b: TVec2): auto = TVec2([a[0] + b[0], a[1] + b[1]]) +func `+`*(a, b: TVec3): auto = TVec3([a[0] + b[0], a[1] + b[1], a[2] + b[2]]) +func `+`*(a, b: TVec4): auto = TVec4([a[0] + b[0], a[1] + b[1], a[2] + b[2], a[ + 3] + b[3]]) +func `-`*(a: TVec2): auto = TVec2([-a[0], -a[1]]) +func `-`*(a: TVec3): auto = TVec3([-a[0], -a[1], -a[2]]) +func `-`*(a: TVec4): auto = TVec4([-a[0], -a[1], -a[2], -a[3]]) +func `-`*(a, b: TVec2): auto = TVec2([a[0] - b[0], a[1] - b[1]]) +func `-`*(a, b: TVec3): auto = TVec3([a[0] - b[0], a[1] - b[1], a[2] - b[2]]) +func `-`*(a, b: TVec4): auto = TVec4([a[0] - b[0], a[1] - b[1], a[2] - b[2], a[ + 3] - b[3]]) +func `*`*(a, b: TVec2): auto = TVec2([a[0] * b[0], a[1] * b[1]]) +func `*`*(a, b: TVec3): auto = TVec3([a[0] * b[0], a[1] * b[1], a[2] * b[2]]) +func `*`*(a, b: TVec4): auto = TVec4([a[0] * b[0], a[1] * b[1], a[2] * b[2], a[ + 3] * b[3]]) +func `/`*[T: SomeInteger](a, b: TVec2[T]): auto = TVec2([a[0] div b[0], a[ + 1] div b[1]]) +func `/`*[T: SomeFloat](a, b: TVec2[T]): auto = TVec2([a[0] / b[0], a[1] / b[1]]) +func `/`*[T: SomeInteger](a, b: TVec3[T]): auto = TVec3([a[0] div b[0], a[ + 1] div b[1], a[2] div b[2]]) +func `/`*[T: SomeFloat](a, b: TVec3[T]): auto = TVec3([a[0] / b[0], a[1] / b[1], + a[2] / b[2]]) +func `/`*[T: SomeInteger](a, b: TVec4[T]): auto = TVec4([a[0] div b[0], a[ + 1] div b[1], a[2] div b[2], a[3] div b[3]]) +func `/`*[T: SomeFloat](a, b: TVec4[T]): auto = TVec4([a[0] / b[0], a[1] / b[1], + a[2] / b[2], a[3] / b[3]]) + +# special operations +func pow*(a: TVec2, b: SomeNumber): auto = + TVec2([pow(a[0], b), pow(a[1], b)]) +func pow*(a: TVec3, b: SomeNumber): auto = + TVec3([pow(a[0], b), pow(a[1], b), pow(a[2], b)]) +func pow*(a: TVec4, b: SomeNumber): auto = + TVec4([pow(a[0], b), pow(a[1], b), pow(a[2], b), pow(a[3], b)]) +func dot*(a, b: TVec2): auto = a[0] * b[0] + a[1] * b[1] +func dot*(a, b: TVec3): auto = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] +func dot*(a, b: TVec4): auto = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] +func cross*(a, b: TVec3): auto = TVec3([ + a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0], +]) + + +# macro to allow creation of new vectors by specifying vector components as attributes +# e.g. myVec.xxy will return a new Vec3 that contains the components x, x an y of the original vector +# (instead of x, y, z for a simple copy) +proc vectorAttributeAccessor(accessor: string): seq[NimNode] = + const ACCESSOR_INDICES = { + 'x': 0, + 'y': 1, + 'z': 2, + 'w': 3, + 'r': 0, + 'g': 1, + 'b': 2, + 'a': 3, + }.toTable + var getterCode, setterCode: NimNode + let accessorvalue = accessor + + if accessorvalue.len == 0: + raise newException(Exception, "empty attribute") + elif accessorvalue.len == 1: + getterCode = nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[accessorvalue[0]])) + setterCode = nnkStmtList.newTree( + nnkAsgn.newTree( + nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[accessorvalue[0]])), ident("value")) + ) + if accessorvalue.len > 1: + var attrs = nnkBracket.newTree() + for attrname in accessorvalue: + attrs.add(nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[attrname]))) + getterCode = nnkCall.newTree(ident("TVec" & $accessorvalue.len), attrs) + setterCode = nnkStmtList.newTree() + var i = 0 + for attrname in accessorvalue: + setterCode.add nnkAsgn.newTree( + nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[attrname])), + nnkBracketExpr.newTree(ident("value"), newLit(i)), + ) + inc i + + result.add newProc( + name = nnkPostfix.newTree(ident("*"), ident(accessor)), + params = [ident("auto"), nnkIdentDefs.newTree(ident("vec"), ident("TVec"), newEmptyNode())], + body = newStmtList(getterCode), + procType = nnkFuncDef, + ) + + result.add nnkFuncDef.newTree( + nnkPostfix.newTree( + newIdentNode("*"), + nnkAccQuoted.newTree(newIdentNode(accessor), newIdentNode("=")) + ), + newEmptyNode(), + nnkGenericParams.newTree(nnkIdentDefs.newTree(newIdentNode("T"), newEmptyNode(), newEmptyNode())), + nnkFormalParams.newTree( + newEmptyNode(), + nnkIdentDefs.newTree( newIdentNode("vec"), nnkVarTy.newTree(newIdentNode("TVec")), newEmptyNode()), + nnkIdentDefs.newTree( newIdentNode("value"), newIdentNode("T"), newEmptyNode()) + ), + newEmptyNode(), + newEmptyNode(), + setterCode + ) + +macro createVectorAttribAccessorFuncs() = + const COORD_ATTRS = ["x", "y", "z", "w"] + const COLOR_ATTRS = ["r", "g", "b", "a"] + result = nnkStmtList.newTree() + for attlist in [COORD_ATTRS, COLOR_ATTRS]: + for i in attlist: + result.add(vectorAttributeAccessor(i)) + for j in attlist: + result.add(vectorAttributeAccessor(i & j)) + for k in attlist: + result.add(vectorAttributeAccessor(i & j & k)) + for l in attlist: + result.add(vectorAttributeAccessor(i & j & k & l)) + +createVectorAttribAccessorFuncs() + +# call e.g. Vec2[int]().randomized() to get a random matrix +template makeRandomInit(mattype: typedesc) = + proc randomized*[T: SomeInteger](m: mattype[T]): mattype[T] = + for i in 0 ..< result.len: + result[i] = rand(low(typeof(m[0])) .. high(typeof(m[0]))) + proc randomized*[T: SomeFloat](m: mattype[T]): mattype[T] = + for i in 0 ..< result.len: + result[i] = rand(1.0) + +makeRandomInit(TVec2) +makeRandomInit(TVec3) +makeRandomInit(TVec4) + +converter Vec2VkExtent*(vec: TVec2[uint32]): VkExtent2D = VkExtent2D(width: vec[0], height: vec[1]) +converter Vec3VkExtent*(vec: TVec2[uint32]): VkExtent3D = VkExtent3D(width: vec[0], height: vec[1], depth: vec[2]) + +func angleBetween*(a, b: Vec3f): float32 = + arccos(a.dot(b) / (a.length * b.length)) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/core/vulkanapi.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/core/vulkanapi.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,12067 @@ +import std/dynlib +import std/tables +import std/strutils +import std/logging +import std/typetraits +import std/macros +type + VkHandle* = distinct uint + VkNonDispatchableHandle* = distinct uint +when defined(linux): + let vulkanLib* = loadLib("libvulkan.so.1") +when defined(windows): + let vulkanLib* = loadLib("vulkan-1.dll") +if vulkanLib == nil: + raise newException(Exception, "Unable to load vulkan library") +func VK_MAKE_API_VERSION*(variant: uint32, major: uint32, minor: uint32, patch: uint32): uint32 {.compileTime.} = + (variant shl 29) or (major shl 22) or (minor shl 12) or patch + +template checkVkResult*(call: untyped) = + when defined(release): + discard call + else: + # yes, a bit cheap, but this is only for nice debug output + var callstr = astToStr(call).replace("\n", "") + while callstr.find(" ") >= 0: + callstr = callstr.replace(" ", " ") + debug "Calling vulkan: ", callstr + let value = call + if value != VK_SUCCESS: + error "Vulkan error: ", astToStr(call), " returned ", $value + raise newException(Exception, "Vulkan error: " & astToStr(call) & + " returned " & $value) +# custom enum iteration (for enum values > 2^16) +macro enumFullRange(a: typed): untyped = + newNimNode(nnkBracket).add(a.getType[1][1..^1]) + +iterator items*[T: HoleyEnum](E: typedesc[T]): T = + for a in enumFullRange(E): yield a +const + VK_MAX_PHYSICAL_DEVICE_NAME_SIZE*: uint32 = 256 + VK_UUID_SIZE*: uint32 = 16 + VK_LUID_SIZE*: uint32 = 8 + VK_LUID_SIZE_KHR* = VK_LUID_SIZE + VK_MAX_EXTENSION_NAME_SIZE*: uint32 = 256 + VK_MAX_DESCRIPTION_SIZE*: uint32 = 256 + VK_MAX_MEMORY_TYPES*: uint32 = 32 + VK_MAX_MEMORY_HEAPS*: uint32 = 16 + VK_LOD_CLAMP_NONE*: float32 = 1000.0F + VK_REMAINING_MIP_LEVELS*: uint32 = not 0'u32 + VK_REMAINING_ARRAY_LAYERS*: uint32 = not 0'u32 + VK_REMAINING_3D_SLICES_EXT*: uint32 = not 0'u32 + VK_WHOLE_SIZE*: uint64 = not 0'u64 + VK_ATTACHMENT_UNUSED*: uint32 = not 0'u32 + VK_TRUE*: uint32 = 1 + VK_FALSE*: uint32 = 0 + VK_QUEUE_FAMILY_IGNORED*: uint32 = not 0'u32 + VK_QUEUE_FAMILY_EXTERNAL*: uint32 = not 1'u32 + VK_QUEUE_FAMILY_EXTERNAL_KHR* = VK_QUEUE_FAMILY_EXTERNAL + VK_QUEUE_FAMILY_FOREIGN_EXT*: uint32 = not 2'u32 + VK_SUBPASS_EXTERNAL*: uint32 = not 0'u32 + VK_MAX_DEVICE_GROUP_SIZE*: uint32 = 32 + VK_MAX_DEVICE_GROUP_SIZE_KHR* = VK_MAX_DEVICE_GROUP_SIZE + VK_MAX_DRIVER_NAME_SIZE*: uint32 = 256 + VK_MAX_DRIVER_NAME_SIZE_KHR* = VK_MAX_DRIVER_NAME_SIZE + VK_MAX_DRIVER_INFO_SIZE*: uint32 = 256 + VK_MAX_DRIVER_INFO_SIZE_KHR* = VK_MAX_DRIVER_INFO_SIZE + VK_SHADER_UNUSED_KHR*: uint32 = not 0'u32 + VK_SHADER_UNUSED_NV* = VK_SHADER_UNUSED_KHR + VK_MAX_GLOBAL_PRIORITY_SIZE_KHR*: uint32 = 16 + VK_MAX_GLOBAL_PRIORITY_SIZE_EXT* = VK_MAX_GLOBAL_PRIORITY_SIZE_KHR + VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT*: uint32 = 32 +type + ANativeWindow* = object + AHardwareBuffer* = object + CAMetalLayer* = object + MTLDevice_id* = object + MTLCommandQueue_id* = object + MTLBuffer_id* = object + MTLTexture_id* = object + MTLSharedEvent_id* = object + IOSurfaceRef* = object + VkSampleMask* = uint32 + VkBool32* = uint32 + VkFlags* = uint32 + VkFlags64* = uint64 + VkDeviceSize* = uint64 + VkDeviceAddress* = uint64 + VkInstance* = distinct VkHandle + VkPhysicalDevice* = distinct VkHandle + VkDevice* = distinct VkHandle + VkQueue* = distinct VkHandle + VkCommandBuffer* = distinct VkHandle + VkDeviceMemory* = distinct VkNonDispatchableHandle + VkCommandPool* = distinct VkNonDispatchableHandle + VkBuffer* = distinct VkNonDispatchableHandle + VkBufferView* = distinct VkNonDispatchableHandle + VkImage* = distinct VkNonDispatchableHandle + VkImageView* = distinct VkNonDispatchableHandle + VkShaderModule* = distinct VkNonDispatchableHandle + VkPipeline* = distinct VkNonDispatchableHandle + VkPipelineLayout* = distinct VkNonDispatchableHandle + VkSampler* = distinct VkNonDispatchableHandle + VkDescriptorSet* = distinct VkNonDispatchableHandle + VkDescriptorSetLayout* = distinct VkNonDispatchableHandle + VkDescriptorPool* = distinct VkNonDispatchableHandle + VkFence* = distinct VkNonDispatchableHandle + VkSemaphore* = distinct VkNonDispatchableHandle + VkEvent* = distinct VkNonDispatchableHandle + VkQueryPool* = distinct VkNonDispatchableHandle + VkFramebuffer* = distinct VkNonDispatchableHandle + VkRenderPass* = distinct VkNonDispatchableHandle + VkPipelineCache* = distinct VkNonDispatchableHandle + VkIndirectCommandsLayoutNV* = distinct VkNonDispatchableHandle + VkDescriptorUpdateTemplate* = distinct VkNonDispatchableHandle + VkSamplerYcbcrConversion* = distinct VkNonDispatchableHandle + VkValidationCacheEXT* = distinct VkNonDispatchableHandle + VkAccelerationStructureKHR* = distinct VkNonDispatchableHandle + VkAccelerationStructureNV* = distinct VkNonDispatchableHandle + VkPerformanceConfigurationINTEL* = distinct VkNonDispatchableHandle + VkBufferCollectionFUCHSIA* = distinct VkNonDispatchableHandle + VkDeferredOperationKHR* = distinct VkNonDispatchableHandle + VkPrivateDataSlot* = distinct VkNonDispatchableHandle + VkCuModuleNVX* = distinct VkNonDispatchableHandle + VkCuFunctionNVX* = distinct VkNonDispatchableHandle + VkOpticalFlowSessionNV* = distinct VkNonDispatchableHandle + VkMicromapEXT* = distinct VkNonDispatchableHandle + VkDisplayKHR* = distinct VkNonDispatchableHandle + VkDisplayModeKHR* = distinct VkNonDispatchableHandle + VkSurfaceKHR* = distinct VkNonDispatchableHandle + VkSwapchainKHR* = distinct VkNonDispatchableHandle + VkDebugReportCallbackEXT* = distinct VkNonDispatchableHandle + VkDebugUtilsMessengerEXT* = distinct VkNonDispatchableHandle + VkVideoSessionKHR* = distinct VkNonDispatchableHandle + VkVideoSessionParametersKHR* = distinct VkNonDispatchableHandle + VkSemaphoreSciSyncPoolNV* = distinct VkNonDispatchableHandle + VkRemoteAddressNV* = pointer +proc `$`*(handle: VkInstance): string = "VkInstance(" & $(uint(handle)) & ")" +proc valid*(handle: VkInstance): bool = uint(handle) != 0 +proc reset*(handle: var VkInstance) = handle = VkInstance(0) +proc `==`*(a, b: VkInstance): bool = uint(a) == uint(b) +proc `$`*(handle: VkPhysicalDevice): string = "VkPhysicalDevice(" & $(uint(handle)) & ")" +proc valid*(handle: VkPhysicalDevice): bool = uint(handle) != 0 +proc reset*(handle: var VkPhysicalDevice) = handle = VkPhysicalDevice(0) +proc `==`*(a, b: VkPhysicalDevice): bool = uint(a) == uint(b) +proc `$`*(handle: VkDevice): string = "VkDevice(" & $(uint(handle)) & ")" +proc valid*(handle: VkDevice): bool = uint(handle) != 0 +proc reset*(handle: var VkDevice) = handle = VkDevice(0) +proc `==`*(a, b: VkDevice): bool = uint(a) == uint(b) +proc `$`*(handle: VkQueue): string = "VkQueue(" & $(uint(handle)) & ")" +proc valid*(handle: VkQueue): bool = uint(handle) != 0 +proc reset*(handle: var VkQueue) = handle = VkQueue(0) +proc `==`*(a, b: VkQueue): bool = uint(a) == uint(b) +proc `$`*(handle: VkCommandBuffer): string = "VkCommandBuffer(" & $(uint(handle)) & ")" +proc valid*(handle: VkCommandBuffer): bool = uint(handle) != 0 +proc reset*(handle: var VkCommandBuffer) = handle = VkCommandBuffer(0) +proc `==`*(a, b: VkCommandBuffer): bool = uint(a) == uint(b) +proc `$`*(handle: VkDeviceMemory): string = "VkDeviceMemory(" & $(uint(handle)) & ")" +proc valid*(handle: VkDeviceMemory): bool = uint(handle) != 0 +proc reset*(handle: var VkDeviceMemory) = handle = VkDeviceMemory(0) +proc `==`*(a, b: VkDeviceMemory): bool = uint(a) == uint(b) +proc `$`*(handle: VkCommandPool): string = "VkCommandPool(" & $(uint(handle)) & ")" +proc valid*(handle: VkCommandPool): bool = uint(handle) != 0 +proc reset*(handle: var VkCommandPool) = handle = VkCommandPool(0) +proc `==`*(a, b: VkCommandPool): bool = uint(a) == uint(b) +proc `$`*(handle: VkBuffer): string = "VkBuffer(" & $(uint(handle)) & ")" +proc valid*(handle: VkBuffer): bool = uint(handle) != 0 +proc reset*(handle: var VkBuffer) = handle = VkBuffer(0) +proc `==`*(a, b: VkBuffer): bool = uint(a) == uint(b) +proc `$`*(handle: VkBufferView): string = "VkBufferView(" & $(uint(handle)) & ")" +proc valid*(handle: VkBufferView): bool = uint(handle) != 0 +proc reset*(handle: var VkBufferView) = handle = VkBufferView(0) +proc `==`*(a, b: VkBufferView): bool = uint(a) == uint(b) +proc `$`*(handle: VkImage): string = "VkImage(" & $(uint(handle)) & ")" +proc valid*(handle: VkImage): bool = uint(handle) != 0 +proc reset*(handle: var VkImage) = handle = VkImage(0) +proc `==`*(a, b: VkImage): bool = uint(a) == uint(b) +proc `$`*(handle: VkImageView): string = "VkImageView(" & $(uint(handle)) & ")" +proc valid*(handle: VkImageView): bool = uint(handle) != 0 +proc reset*(handle: var VkImageView) = handle = VkImageView(0) +proc `==`*(a, b: VkImageView): bool = uint(a) == uint(b) +proc `$`*(handle: VkShaderModule): string = "VkShaderModule(" & $(uint(handle)) & ")" +proc valid*(handle: VkShaderModule): bool = uint(handle) != 0 +proc reset*(handle: var VkShaderModule) = handle = VkShaderModule(0) +proc `==`*(a, b: VkShaderModule): bool = uint(a) == uint(b) +proc `$`*(handle: VkPipeline): string = "VkPipeline(" & $(uint(handle)) & ")" +proc valid*(handle: VkPipeline): bool = uint(handle) != 0 +proc reset*(handle: var VkPipeline) = handle = VkPipeline(0) +proc `==`*(a, b: VkPipeline): bool = uint(a) == uint(b) +proc `$`*(handle: VkPipelineLayout): string = "VkPipelineLayout(" & $(uint(handle)) & ")" +proc valid*(handle: VkPipelineLayout): bool = uint(handle) != 0 +proc reset*(handle: var VkPipelineLayout) = handle = VkPipelineLayout(0) +proc `==`*(a, b: VkPipelineLayout): bool = uint(a) == uint(b) +proc `$`*(handle: VkSampler): string = "VkSampler(" & $(uint(handle)) & ")" +proc valid*(handle: VkSampler): bool = uint(handle) != 0 +proc reset*(handle: var VkSampler) = handle = VkSampler(0) +proc `==`*(a, b: VkSampler): bool = uint(a) == uint(b) +proc `$`*(handle: VkDescriptorSet): string = "VkDescriptorSet(" & $(uint(handle)) & ")" +proc valid*(handle: VkDescriptorSet): bool = uint(handle) != 0 +proc reset*(handle: var VkDescriptorSet) = handle = VkDescriptorSet(0) +proc `==`*(a, b: VkDescriptorSet): bool = uint(a) == uint(b) +proc `$`*(handle: VkDescriptorSetLayout): string = "VkDescriptorSetLayout(" & $(uint(handle)) & ")" +proc valid*(handle: VkDescriptorSetLayout): bool = uint(handle) != 0 +proc reset*(handle: var VkDescriptorSetLayout) = handle = VkDescriptorSetLayout(0) +proc `==`*(a, b: VkDescriptorSetLayout): bool = uint(a) == uint(b) +proc `$`*(handle: VkDescriptorPool): string = "VkDescriptorPool(" & $(uint(handle)) & ")" +proc valid*(handle: VkDescriptorPool): bool = uint(handle) != 0 +proc reset*(handle: var VkDescriptorPool) = handle = VkDescriptorPool(0) +proc `==`*(a, b: VkDescriptorPool): bool = uint(a) == uint(b) +proc `$`*(handle: VkFence): string = "VkFence(" & $(uint(handle)) & ")" +proc valid*(handle: VkFence): bool = uint(handle) != 0 +proc reset*(handle: var VkFence) = handle = VkFence(0) +proc `==`*(a, b: VkFence): bool = uint(a) == uint(b) +proc `$`*(handle: VkSemaphore): string = "VkSemaphore(" & $(uint(handle)) & ")" +proc valid*(handle: VkSemaphore): bool = uint(handle) != 0 +proc reset*(handle: var VkSemaphore) = handle = VkSemaphore(0) +proc `==`*(a, b: VkSemaphore): bool = uint(a) == uint(b) +proc `$`*(handle: VkEvent): string = "VkEvent(" & $(uint(handle)) & ")" +proc valid*(handle: VkEvent): bool = uint(handle) != 0 +proc reset*(handle: var VkEvent) = handle = VkEvent(0) +proc `==`*(a, b: VkEvent): bool = uint(a) == uint(b) +proc `$`*(handle: VkQueryPool): string = "VkQueryPool(" & $(uint(handle)) & ")" +proc valid*(handle: VkQueryPool): bool = uint(handle) != 0 +proc reset*(handle: var VkQueryPool) = handle = VkQueryPool(0) +proc `==`*(a, b: VkQueryPool): bool = uint(a) == uint(b) +proc `$`*(handle: VkFramebuffer): string = "VkFramebuffer(" & $(uint(handle)) & ")" +proc valid*(handle: VkFramebuffer): bool = uint(handle) != 0 +proc reset*(handle: var VkFramebuffer) = handle = VkFramebuffer(0) +proc `==`*(a, b: VkFramebuffer): bool = uint(a) == uint(b) +proc `$`*(handle: VkRenderPass): string = "VkRenderPass(" & $(uint(handle)) & ")" +proc valid*(handle: VkRenderPass): bool = uint(handle) != 0 +proc reset*(handle: var VkRenderPass) = handle = VkRenderPass(0) +proc `==`*(a, b: VkRenderPass): bool = uint(a) == uint(b) +proc `$`*(handle: VkPipelineCache): string = "VkPipelineCache(" & $(uint(handle)) & ")" +proc valid*(handle: VkPipelineCache): bool = uint(handle) != 0 +proc reset*(handle: var VkPipelineCache) = handle = VkPipelineCache(0) +proc `==`*(a, b: VkPipelineCache): bool = uint(a) == uint(b) +proc `$`*(handle: VkIndirectCommandsLayoutNV): string = "VkIndirectCommandsLayoutNV(" & $(uint(handle)) & ")" +proc valid*(handle: VkIndirectCommandsLayoutNV): bool = uint(handle) != 0 +proc reset*(handle: var VkIndirectCommandsLayoutNV) = handle = VkIndirectCommandsLayoutNV(0) +proc `==`*(a, b: VkIndirectCommandsLayoutNV): bool = uint(a) == uint(b) +proc `$`*(handle: VkDescriptorUpdateTemplate): string = "VkDescriptorUpdateTemplate(" & $(uint(handle)) & ")" +proc valid*(handle: VkDescriptorUpdateTemplate): bool = uint(handle) != 0 +proc reset*(handle: var VkDescriptorUpdateTemplate) = handle = VkDescriptorUpdateTemplate(0) +proc `==`*(a, b: VkDescriptorUpdateTemplate): bool = uint(a) == uint(b) +proc `$`*(handle: VkSamplerYcbcrConversion): string = "VkSamplerYcbcrConversion(" & $(uint(handle)) & ")" +proc valid*(handle: VkSamplerYcbcrConversion): bool = uint(handle) != 0 +proc reset*(handle: var VkSamplerYcbcrConversion) = handle = VkSamplerYcbcrConversion(0) +proc `==`*(a, b: VkSamplerYcbcrConversion): bool = uint(a) == uint(b) +proc `$`*(handle: VkValidationCacheEXT): string = "VkValidationCacheEXT(" & $(uint(handle)) & ")" +proc valid*(handle: VkValidationCacheEXT): bool = uint(handle) != 0 +proc reset*(handle: var VkValidationCacheEXT) = handle = VkValidationCacheEXT(0) +proc `==`*(a, b: VkValidationCacheEXT): bool = uint(a) == uint(b) +proc `$`*(handle: VkAccelerationStructureKHR): string = "VkAccelerationStructureKHR(" & $(uint(handle)) & ")" +proc valid*(handle: VkAccelerationStructureKHR): bool = uint(handle) != 0 +proc reset*(handle: var VkAccelerationStructureKHR) = handle = VkAccelerationStructureKHR(0) +proc `==`*(a, b: VkAccelerationStructureKHR): bool = uint(a) == uint(b) +proc `$`*(handle: VkAccelerationStructureNV): string = "VkAccelerationStructureNV(" & $(uint(handle)) & ")" +proc valid*(handle: VkAccelerationStructureNV): bool = uint(handle) != 0 +proc reset*(handle: var VkAccelerationStructureNV) = handle = VkAccelerationStructureNV(0) +proc `==`*(a, b: VkAccelerationStructureNV): bool = uint(a) == uint(b) +proc `$`*(handle: VkPerformanceConfigurationINTEL): string = "VkPerformanceConfigurationINTEL(" & $(uint(handle)) & ")" +proc valid*(handle: VkPerformanceConfigurationINTEL): bool = uint(handle) != 0 +proc reset*(handle: var VkPerformanceConfigurationINTEL) = handle = VkPerformanceConfigurationINTEL(0) +proc `==`*(a, b: VkPerformanceConfigurationINTEL): bool = uint(a) == uint(b) +proc `$`*(handle: VkBufferCollectionFUCHSIA): string = "VkBufferCollectionFUCHSIA(" & $(uint(handle)) & ")" +proc valid*(handle: VkBufferCollectionFUCHSIA): bool = uint(handle) != 0 +proc reset*(handle: var VkBufferCollectionFUCHSIA) = handle = VkBufferCollectionFUCHSIA(0) +proc `==`*(a, b: VkBufferCollectionFUCHSIA): bool = uint(a) == uint(b) +proc `$`*(handle: VkDeferredOperationKHR): string = "VkDeferredOperationKHR(" & $(uint(handle)) & ")" +proc valid*(handle: VkDeferredOperationKHR): bool = uint(handle) != 0 +proc reset*(handle: var VkDeferredOperationKHR) = handle = VkDeferredOperationKHR(0) +proc `==`*(a, b: VkDeferredOperationKHR): bool = uint(a) == uint(b) +proc `$`*(handle: VkPrivateDataSlot): string = "VkPrivateDataSlot(" & $(uint(handle)) & ")" +proc valid*(handle: VkPrivateDataSlot): bool = uint(handle) != 0 +proc reset*(handle: var VkPrivateDataSlot) = handle = VkPrivateDataSlot(0) +proc `==`*(a, b: VkPrivateDataSlot): bool = uint(a) == uint(b) +proc `$`*(handle: VkCuModuleNVX): string = "VkCuModuleNVX(" & $(uint(handle)) & ")" +proc valid*(handle: VkCuModuleNVX): bool = uint(handle) != 0 +proc reset*(handle: var VkCuModuleNVX) = handle = VkCuModuleNVX(0) +proc `==`*(a, b: VkCuModuleNVX): bool = uint(a) == uint(b) +proc `$`*(handle: VkCuFunctionNVX): string = "VkCuFunctionNVX(" & $(uint(handle)) & ")" +proc valid*(handle: VkCuFunctionNVX): bool = uint(handle) != 0 +proc reset*(handle: var VkCuFunctionNVX) = handle = VkCuFunctionNVX(0) +proc `==`*(a, b: VkCuFunctionNVX): bool = uint(a) == uint(b) +proc `$`*(handle: VkOpticalFlowSessionNV): string = "VkOpticalFlowSessionNV(" & $(uint(handle)) & ")" +proc valid*(handle: VkOpticalFlowSessionNV): bool = uint(handle) != 0 +proc reset*(handle: var VkOpticalFlowSessionNV) = handle = VkOpticalFlowSessionNV(0) +proc `==`*(a, b: VkOpticalFlowSessionNV): bool = uint(a) == uint(b) +proc `$`*(handle: VkMicromapEXT): string = "VkMicromapEXT(" & $(uint(handle)) & ")" +proc valid*(handle: VkMicromapEXT): bool = uint(handle) != 0 +proc reset*(handle: var VkMicromapEXT) = handle = VkMicromapEXT(0) +proc `==`*(a, b: VkMicromapEXT): bool = uint(a) == uint(b) +proc `$`*(handle: VkDisplayKHR): string = "VkDisplayKHR(" & $(uint(handle)) & ")" +proc valid*(handle: VkDisplayKHR): bool = uint(handle) != 0 +proc reset*(handle: var VkDisplayKHR) = handle = VkDisplayKHR(0) +proc `==`*(a, b: VkDisplayKHR): bool = uint(a) == uint(b) +proc `$`*(handle: VkDisplayModeKHR): string = "VkDisplayModeKHR(" & $(uint(handle)) & ")" +proc valid*(handle: VkDisplayModeKHR): bool = uint(handle) != 0 +proc reset*(handle: var VkDisplayModeKHR) = handle = VkDisplayModeKHR(0) +proc `==`*(a, b: VkDisplayModeKHR): bool = uint(a) == uint(b) +proc `$`*(handle: VkSurfaceKHR): string = "VkSurfaceKHR(" & $(uint(handle)) & ")" +proc valid*(handle: VkSurfaceKHR): bool = uint(handle) != 0 +proc reset*(handle: var VkSurfaceKHR) = handle = VkSurfaceKHR(0) +proc `==`*(a, b: VkSurfaceKHR): bool = uint(a) == uint(b) +proc `$`*(handle: VkSwapchainKHR): string = "VkSwapchainKHR(" & $(uint(handle)) & ")" +proc valid*(handle: VkSwapchainKHR): bool = uint(handle) != 0 +proc reset*(handle: var VkSwapchainKHR) = handle = VkSwapchainKHR(0) +proc `==`*(a, b: VkSwapchainKHR): bool = uint(a) == uint(b) +proc `$`*(handle: VkDebugReportCallbackEXT): string = "VkDebugReportCallbackEXT(" & $(uint(handle)) & ")" +proc valid*(handle: VkDebugReportCallbackEXT): bool = uint(handle) != 0 +proc reset*(handle: var VkDebugReportCallbackEXT) = handle = VkDebugReportCallbackEXT(0) +proc `==`*(a, b: VkDebugReportCallbackEXT): bool = uint(a) == uint(b) +proc `$`*(handle: VkDebugUtilsMessengerEXT): string = "VkDebugUtilsMessengerEXT(" & $(uint(handle)) & ")" +proc valid*(handle: VkDebugUtilsMessengerEXT): bool = uint(handle) != 0 +proc reset*(handle: var VkDebugUtilsMessengerEXT) = handle = VkDebugUtilsMessengerEXT(0) +proc `==`*(a, b: VkDebugUtilsMessengerEXT): bool = uint(a) == uint(b) +proc `$`*(handle: VkVideoSessionKHR): string = "VkVideoSessionKHR(" & $(uint(handle)) & ")" +proc valid*(handle: VkVideoSessionKHR): bool = uint(handle) != 0 +proc reset*(handle: var VkVideoSessionKHR) = handle = VkVideoSessionKHR(0) +proc `==`*(a, b: VkVideoSessionKHR): bool = uint(a) == uint(b) +proc `$`*(handle: VkVideoSessionParametersKHR): string = "VkVideoSessionParametersKHR(" & $(uint(handle)) & ")" +proc valid*(handle: VkVideoSessionParametersKHR): bool = uint(handle) != 0 +proc reset*(handle: var VkVideoSessionParametersKHR) = handle = VkVideoSessionParametersKHR(0) +proc `==`*(a, b: VkVideoSessionParametersKHR): bool = uint(a) == uint(b) +proc `$`*(handle: VkSemaphoreSciSyncPoolNV): string = "VkSemaphoreSciSyncPoolNV(" & $(uint(handle)) & ")" +proc valid*(handle: VkSemaphoreSciSyncPoolNV): bool = uint(handle) != 0 +proc reset*(handle: var VkSemaphoreSciSyncPoolNV) = handle = VkSemaphoreSciSyncPoolNV(0) +proc `==`*(a, b: VkSemaphoreSciSyncPoolNV): bool = uint(a) == uint(b) +type + VkFramebufferCreateFlags* = distinct VkFlags + VkQueryPoolCreateFlags* = distinct VkFlags + VkRenderPassCreateFlags* = distinct VkFlags + VkSamplerCreateFlags* = distinct VkFlags + VkPipelineLayoutCreateFlags* = distinct VkFlags + VkPipelineCacheCreateFlags* = distinct VkFlags + VkPipelineDepthStencilStateCreateFlags* = distinct VkFlags + VkPipelineDynamicStateCreateFlags* = distinct VkFlags + VkPipelineColorBlendStateCreateFlags* = distinct VkFlags + VkPipelineMultisampleStateCreateFlags* = distinct VkFlags + VkPipelineRasterizationStateCreateFlags* = distinct VkFlags + VkPipelineViewportStateCreateFlags* = distinct VkFlags + VkPipelineTessellationStateCreateFlags* = distinct VkFlags + VkPipelineInputAssemblyStateCreateFlags* = distinct VkFlags + VkPipelineVertexInputStateCreateFlags* = distinct VkFlags + VkPipelineShaderStageCreateFlags* = distinct VkFlags + VkDescriptorSetLayoutCreateFlags* = distinct VkFlags + VkBufferViewCreateFlags* = distinct VkFlags + VkInstanceCreateFlags* = distinct VkFlags + VkDeviceCreateFlags* = distinct VkFlags + VkDeviceQueueCreateFlags* = distinct VkFlags + VkQueueFlags* = distinct VkFlags + VkMemoryPropertyFlags* = distinct VkFlags + VkMemoryHeapFlags* = distinct VkFlags + VkAccessFlags* = distinct VkFlags + VkBufferUsageFlags* = distinct VkFlags + VkBufferCreateFlags* = distinct VkFlags + VkShaderStageFlags* = distinct VkFlags + VkImageUsageFlags* = distinct VkFlags + VkImageCreateFlags* = distinct VkFlags + VkImageViewCreateFlags* = distinct VkFlags + VkPipelineCreateFlags* = distinct VkFlags + VkColorComponentFlags* = distinct VkFlags + VkFenceCreateFlags* = distinct VkFlags + VkSemaphoreCreateFlags* = distinct VkFlags + VkFormatFeatureFlags* = distinct VkFlags + VkQueryControlFlags* = distinct VkFlags + VkQueryResultFlags* = distinct VkFlags + VkShaderModuleCreateFlags* = distinct VkFlags + VkEventCreateFlags* = distinct VkFlags + VkCommandPoolCreateFlags* = distinct VkFlags + VkCommandPoolResetFlags* = distinct VkFlags + VkCommandBufferResetFlags* = distinct VkFlags + VkCommandBufferUsageFlags* = distinct VkFlags + VkQueryPipelineStatisticFlags* = distinct VkFlags + VkMemoryMapFlags* = distinct VkFlags + VkImageAspectFlags* = distinct VkFlags + VkSparseMemoryBindFlags* = distinct VkFlags + VkSparseImageFormatFlags* = distinct VkFlags + VkSubpassDescriptionFlags* = distinct VkFlags + VkPipelineStageFlags* = distinct VkFlags + VkSampleCountFlags* = distinct VkFlags + VkAttachmentDescriptionFlags* = distinct VkFlags + VkStencilFaceFlags* = distinct VkFlags + VkCullModeFlags* = distinct VkFlags + VkDescriptorPoolCreateFlags* = distinct VkFlags + VkDescriptorPoolResetFlags* = distinct VkFlags + VkDependencyFlags* = distinct VkFlags + VkSubgroupFeatureFlags* = distinct VkFlags + VkIndirectCommandsLayoutUsageFlagsNV* = distinct VkFlags + VkIndirectStateFlagsNV* = distinct VkFlags + VkGeometryFlagsKHR* = distinct VkFlags + VkGeometryInstanceFlagsKHR* = distinct VkFlags + VkBuildAccelerationStructureFlagsKHR* = distinct VkFlags + VkPrivateDataSlotCreateFlags* = distinct VkFlags + VkAccelerationStructureCreateFlagsKHR* = distinct VkFlags + VkDescriptorUpdateTemplateCreateFlags* = distinct VkFlags + VkPipelineCreationFeedbackFlags* = distinct VkFlags + VkPerformanceCounterDescriptionFlagsKHR* = distinct VkFlags + VkAcquireProfilingLockFlagsKHR* = distinct VkFlags + VkSemaphoreWaitFlags* = distinct VkFlags + VkPipelineCompilerControlFlagsAMD* = distinct VkFlags + VkShaderCorePropertiesFlagsAMD* = distinct VkFlags + VkDeviceDiagnosticsConfigFlagsNV* = distinct VkFlags + VkRefreshObjectFlagsKHR* = distinct VkFlags + VkAccessFlags2* = distinct VkFlags + VkPipelineStageFlags2* = distinct VkFlags + VkAccelerationStructureMotionInfoFlagsNV* = distinct VkFlags + VkAccelerationStructureMotionInstanceFlagsNV* = distinct VkFlags + VkFormatFeatureFlags2* = distinct VkFlags + VkRenderingFlags* = distinct VkFlags + VkMemoryDecompressionMethodFlagsNV* = distinct VkFlags + VkBuildMicromapFlagsEXT* = distinct VkFlags + VkMicromapCreateFlagsEXT* = distinct VkFlags + VkDirectDriverLoadingFlagsLUNARG* = distinct VkFlags + VkCompositeAlphaFlagsKHR* = distinct VkFlags + VkDisplayPlaneAlphaFlagsKHR* = distinct VkFlags + VkSurfaceTransformFlagsKHR* = distinct VkFlags + VkSwapchainCreateFlagsKHR* = distinct VkFlags + VkDisplayModeCreateFlagsKHR* = distinct VkFlags + VkDisplaySurfaceCreateFlagsKHR* = distinct VkFlags + VkAndroidSurfaceCreateFlagsKHR* = distinct VkFlags + VkViSurfaceCreateFlagsNN* = distinct VkFlags + VkWaylandSurfaceCreateFlagsKHR* = distinct VkFlags + VkWin32SurfaceCreateFlagsKHR* = distinct VkFlags + VkXlibSurfaceCreateFlagsKHR* = distinct VkFlags + VkXcbSurfaceCreateFlagsKHR* = distinct VkFlags + VkDirectFBSurfaceCreateFlagsEXT* = distinct VkFlags + VkIOSSurfaceCreateFlagsMVK* = distinct VkFlags + VkMacOSSurfaceCreateFlagsMVK* = distinct VkFlags + VkMetalSurfaceCreateFlagsEXT* = distinct VkFlags + VkImagePipeSurfaceCreateFlagsFUCHSIA* = distinct VkFlags + VkStreamDescriptorSurfaceCreateFlagsGGP* = distinct VkFlags + VkHeadlessSurfaceCreateFlagsEXT* = distinct VkFlags + VkScreenSurfaceCreateFlagsQNX* = distinct VkFlags + VkPeerMemoryFeatureFlags* = distinct VkFlags + VkMemoryAllocateFlags* = distinct VkFlags + VkDeviceGroupPresentModeFlagsKHR* = distinct VkFlags + VkDebugReportFlagsEXT* = distinct VkFlags + VkCommandPoolTrimFlags* = distinct VkFlags + VkExternalMemoryHandleTypeFlagsNV* = distinct VkFlags + VkExternalMemoryFeatureFlagsNV* = distinct VkFlags + VkExternalMemoryHandleTypeFlags* = distinct VkFlags + VkExternalMemoryFeatureFlags* = distinct VkFlags + VkExternalSemaphoreHandleTypeFlags* = distinct VkFlags + VkExternalSemaphoreFeatureFlags* = distinct VkFlags + VkSemaphoreImportFlags* = distinct VkFlags + VkExternalFenceHandleTypeFlags* = distinct VkFlags + VkExternalFenceFeatureFlags* = distinct VkFlags + VkFenceImportFlags* = distinct VkFlags + VkSurfaceCounterFlagsEXT* = distinct VkFlags + VkPipelineViewportSwizzleStateCreateFlagsNV* = distinct VkFlags + VkPipelineDiscardRectangleStateCreateFlagsEXT* = distinct VkFlags + VkPipelineCoverageToColorStateCreateFlagsNV* = distinct VkFlags + VkPipelineCoverageModulationStateCreateFlagsNV* = distinct VkFlags + VkPipelineCoverageReductionStateCreateFlagsNV* = distinct VkFlags + VkValidationCacheCreateFlagsEXT* = distinct VkFlags + VkDebugUtilsMessageSeverityFlagsEXT* = distinct VkFlags + VkDebugUtilsMessageTypeFlagsEXT* = distinct VkFlags + VkDebugUtilsMessengerCreateFlagsEXT* = distinct VkFlags + VkDebugUtilsMessengerCallbackDataFlagsEXT* = distinct VkFlags + VkDeviceMemoryReportFlagsEXT* = distinct VkFlags + VkPipelineRasterizationConservativeStateCreateFlagsEXT* = distinct VkFlags + VkDescriptorBindingFlags* = distinct VkFlags + VkConditionalRenderingFlagsEXT* = distinct VkFlags + VkResolveModeFlags* = distinct VkFlags + VkPipelineRasterizationStateStreamCreateFlagsEXT* = distinct VkFlags + VkPipelineRasterizationDepthClipStateCreateFlagsEXT* = distinct VkFlags + VkSwapchainImageUsageFlagsANDROID* = distinct VkFlags + VkToolPurposeFlags* = distinct VkFlags + VkSubmitFlags* = distinct VkFlags + VkImageFormatConstraintsFlagsFUCHSIA* = distinct VkFlags + VkImageConstraintsInfoFlagsFUCHSIA* = distinct VkFlags + VkGraphicsPipelineLibraryFlagsEXT* = distinct VkFlags + VkImageCompressionFlagsEXT* = distinct VkFlags + VkImageCompressionFixedRateFlagsEXT* = distinct VkFlags + VkExportMetalObjectTypeFlagsEXT* = distinct VkFlags + VkDeviceAddressBindingFlagsEXT* = distinct VkFlags + VkOpticalFlowGridSizeFlagsNV* = distinct VkFlags + VkOpticalFlowUsageFlagsNV* = distinct VkFlags + VkOpticalFlowSessionCreateFlagsNV* = distinct VkFlags + VkOpticalFlowExecuteFlagsNV* = distinct VkFlags + VkPresentScalingFlagsEXT* = distinct VkFlags + VkPresentGravityFlagsEXT* = distinct VkFlags + VkVideoCodecOperationFlagsKHR* = distinct VkFlags + VkVideoCapabilityFlagsKHR* = distinct VkFlags + VkVideoSessionCreateFlagsKHR* = distinct VkFlags + VkVideoSessionParametersCreateFlagsKHR* = distinct VkFlags + VkVideoBeginCodingFlagsKHR* = distinct VkFlags + VkVideoEndCodingFlagsKHR* = distinct VkFlags + VkVideoCodingControlFlagsKHR* = distinct VkFlags + VkVideoDecodeUsageFlagsKHR* = distinct VkFlags + VkVideoDecodeCapabilityFlagsKHR* = distinct VkFlags + VkVideoDecodeFlagsKHR* = distinct VkFlags + VkVideoDecodeH264PictureLayoutFlagsKHR* = distinct VkFlags + VkVideoEncodeFlagsKHR* = distinct VkFlags + VkVideoEncodeUsageFlagsKHR* = distinct VkFlags + VkVideoEncodeContentFlagsKHR* = distinct VkFlags + VkVideoEncodeCapabilityFlagsKHR* = distinct VkFlags + VkVideoEncodeRateControlFlagsKHR* = distinct VkFlags + VkVideoEncodeRateControlModeFlagsKHR* = distinct VkFlags + VkVideoChromaSubsamplingFlagsKHR* = distinct VkFlags + VkVideoComponentBitDepthFlagsKHR* = distinct VkFlags + VkVideoEncodeH264CapabilityFlagsEXT* = distinct VkFlags + VkVideoEncodeH264InputModeFlagsEXT* = distinct VkFlags + VkVideoEncodeH264OutputModeFlagsEXT* = distinct VkFlags + VkVideoEncodeH265CapabilityFlagsEXT* = distinct VkFlags + VkVideoEncodeH265InputModeFlagsEXT* = distinct VkFlags + VkVideoEncodeH265OutputModeFlagsEXT* = distinct VkFlags + VkVideoEncodeH265CtbSizeFlagsEXT* = distinct VkFlags + VkVideoEncodeH265TransformBlockSizeFlagsEXT* = distinct VkFlags +let vkGetInstanceProcAddr = cast[proc(instance: VkInstance, name: cstring): pointer {.stdcall.}](checkedSymAddr(vulkanLib, "vkGetInstanceProcAddr")) +type + VkImageLayout* {.size: sizeof(cint).} = enum + VK_IMAGE_LAYOUT_UNDEFINED = 0 + VK_IMAGE_LAYOUT_GENERAL = 1 + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2 + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3 + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4 + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5 + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6 + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7 + VK_IMAGE_LAYOUT_PREINITIALIZED = 8 + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002 + VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR = 1000024000 + VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR = 1000024001 + VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR = 1000024002 + VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000 + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000 + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001 + VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR = 1000164003 + VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000 + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000 + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001 + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002 + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003 + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR = 1000299000 + VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR = 1000299001 + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR = 1000299002 + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL = 1000314000 + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL = 1000314001 + VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT = 1000339000 + VkAttachmentLoadOp* {.size: sizeof(cint).} = enum + VK_ATTACHMENT_LOAD_OP_LOAD = 0 + VK_ATTACHMENT_LOAD_OP_CLEAR = 1 + VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2 + VK_ATTACHMENT_LOAD_OP_NONE_EXT = 1000400000 + VkAttachmentStoreOp* {.size: sizeof(cint).} = enum + VK_ATTACHMENT_STORE_OP_STORE = 0 + VK_ATTACHMENT_STORE_OP_DONT_CARE = 1 + VK_ATTACHMENT_STORE_OP_NONE = 1000301000 + VkImageType* {.size: sizeof(cint).} = enum + VK_IMAGE_TYPE_1D = 0 + VK_IMAGE_TYPE_2D = 1 + VK_IMAGE_TYPE_3D = 2 + VkImageTiling* {.size: sizeof(cint).} = enum + VK_IMAGE_TILING_OPTIMAL = 0 + VK_IMAGE_TILING_LINEAR = 1 + VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT = 1000158000 + VkImageViewType* {.size: sizeof(cint).} = enum + VK_IMAGE_VIEW_TYPE_1D = 0 + VK_IMAGE_VIEW_TYPE_2D = 1 + VK_IMAGE_VIEW_TYPE_3D = 2 + VK_IMAGE_VIEW_TYPE_CUBE = 3 + VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4 + VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5 + VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6 + VkCommandBufferLevel* {.size: sizeof(cint).} = enum + VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0 + VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1 + VkComponentSwizzle* {.size: sizeof(cint).} = enum + VK_COMPONENT_SWIZZLE_IDENTITY = 0 + VK_COMPONENT_SWIZZLE_ZERO = 1 + VK_COMPONENT_SWIZZLE_ONE = 2 + VK_COMPONENT_SWIZZLE_R = 3 + VK_COMPONENT_SWIZZLE_G = 4 + VK_COMPONENT_SWIZZLE_B = 5 + VK_COMPONENT_SWIZZLE_A = 6 + VkDescriptorType* {.size: sizeof(cint).} = enum + VK_DESCRIPTOR_TYPE_SAMPLER = 0 + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1 + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2 + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3 + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4 + VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5 + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6 + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7 + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8 + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9 + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10 + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000 + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000 + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000 + VK_DESCRIPTOR_TYPE_MUTABLE_EXT = 1000351000 + VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000 + VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001 + VkQueryType* {.size: sizeof(cint).} = enum + VK_QUERY_TYPE_OCCLUSION = 0 + VK_QUERY_TYPE_PIPELINE_STATISTICS = 1 + VK_QUERY_TYPE_TIMESTAMP = 2 + VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR = 1000023000 + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004 + VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR = 1000116000 + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000150000 + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150001 + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000 + VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000 + VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR = 1000299000 + VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT = 1000328000 + VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT = 1000382000 + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR = 1000386000 + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR = 1000386001 + VK_QUERY_TYPE_MICROMAP_SERIALIZATION_SIZE_EXT = 1000396000 + VK_QUERY_TYPE_MICROMAP_COMPACTED_SIZE_EXT = 1000396001 + VkBorderColor* {.size: sizeof(cint).} = enum + VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0 + VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1 + VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2 + VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3 + VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4 + VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5 + VK_BORDER_COLOR_FLOAT_CUSTOM_EXT = 1000287003 + VK_BORDER_COLOR_INT_CUSTOM_EXT = 1000287004 + VkPipelineBindPoint* {.size: sizeof(cint).} = enum + VK_PIPELINE_BIND_POINT_GRAPHICS = 0 + VK_PIPELINE_BIND_POINT_COMPUTE = 1 + VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000 + VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI = 1000369003 + VkPipelineCacheHeaderVersion* {.size: sizeof(cint).} = enum + VK_PIPELINE_CACHE_HEADER_VERSION_ONE_ENUM = 1 + VK_PIPELINE_CACHE_HEADER_VERSION_SAFETY_CRITICAL_ONE_ENUM = 1000298001 + VkPipelineCacheCreateFlagBits* {.size: sizeof(cint).} = enum + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0b00000000000000000000000000000001 + VK_PIPELINE_CACHE_CREATE_RESERVED_1_BIT_EXT = 0b00000000000000000000000000000010 + VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkPipelineCacheCreateFlagBits]): VkPipelineCacheCreateFlags = + for flag in flags: + result = VkPipelineCacheCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkPipelineCacheCreateFlags): seq[VkPipelineCacheCreateFlagBits] = + for value in VkPipelineCacheCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPipelineCacheCreateFlags): bool = cint(a) == cint(b) +type + VkPrimitiveTopology* {.size: sizeof(cint).} = enum + VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0 + VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1 + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2 + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3 + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4 + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5 + VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6 + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7 + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8 + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9 + VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10 + VkSharingMode* {.size: sizeof(cint).} = enum + VK_SHARING_MODE_EXCLUSIVE = 0 + VK_SHARING_MODE_CONCURRENT = 1 + VkIndexType* {.size: sizeof(cint).} = enum + VK_INDEX_TYPE_UINT16 = 0 + VK_INDEX_TYPE_UINT32 = 1 + VK_INDEX_TYPE_NONE_KHR = 1000165000 + VK_INDEX_TYPE_UINT8_EXT = 1000265000 + VkFilter* {.size: sizeof(cint).} = enum + VK_FILTER_NEAREST = 0 + VK_FILTER_LINEAR = 1 + VK_FILTER_CUBIC_EXT = 1000015000 + VkSamplerMipmapMode* {.size: sizeof(cint).} = enum + VK_SAMPLER_MIPMAP_MODE_NEAREST = 0 + VK_SAMPLER_MIPMAP_MODE_LINEAR = 1 + VkSamplerAddressMode* {.size: sizeof(cint).} = enum + VK_SAMPLER_ADDRESS_MODE_REPEAT = 0 + VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1 + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2 + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3 + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4 + VkCompareOp* {.size: sizeof(cint).} = enum + VK_COMPARE_OP_NEVER = 0 + VK_COMPARE_OP_LESS = 1 + VK_COMPARE_OP_EQUAL = 2 + VK_COMPARE_OP_LESS_OR_EQUAL = 3 + VK_COMPARE_OP_GREATER = 4 + VK_COMPARE_OP_NOT_EQUAL = 5 + VK_COMPARE_OP_GREATER_OR_EQUAL = 6 + VK_COMPARE_OP_ALWAYS = 7 + VkPolygonMode* {.size: sizeof(cint).} = enum + VK_POLYGON_MODE_FILL = 0 + VK_POLYGON_MODE_LINE = 1 + VK_POLYGON_MODE_POINT = 2 + VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000 + VkFrontFace* {.size: sizeof(cint).} = enum + VK_FRONT_FACE_COUNTER_CLOCKWISE = 0 + VK_FRONT_FACE_CLOCKWISE = 1 + VkBlendFactor* {.size: sizeof(cint).} = enum + VK_BLEND_FACTOR_ZERO = 0 + VK_BLEND_FACTOR_ONE = 1 + VK_BLEND_FACTOR_SRC_COLOR = 2 + VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3 + VK_BLEND_FACTOR_DST_COLOR = 4 + VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5 + VK_BLEND_FACTOR_SRC_ALPHA = 6 + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7 + VK_BLEND_FACTOR_DST_ALPHA = 8 + VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9 + VK_BLEND_FACTOR_CONSTANT_COLOR = 10 + VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11 + VK_BLEND_FACTOR_CONSTANT_ALPHA = 12 + VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13 + VK_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14 + VK_BLEND_FACTOR_SRC1_COLOR = 15 + VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16 + VK_BLEND_FACTOR_SRC1_ALPHA = 17 + VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18 + VkBlendOp* {.size: sizeof(cint).} = enum + VK_BLEND_OP_ADD = 0 + VK_BLEND_OP_SUBTRACT = 1 + VK_BLEND_OP_REVERSE_SUBTRACT = 2 + VK_BLEND_OP_MIN = 3 + VK_BLEND_OP_MAX = 4 + VK_BLEND_OP_ZERO_EXT = 1000148000 + VK_BLEND_OP_SRC_EXT = 1000148001 + VK_BLEND_OP_DST_EXT = 1000148002 + VK_BLEND_OP_SRC_OVER_EXT = 1000148003 + VK_BLEND_OP_DST_OVER_EXT = 1000148004 + VK_BLEND_OP_SRC_IN_EXT = 1000148005 + VK_BLEND_OP_DST_IN_EXT = 1000148006 + VK_BLEND_OP_SRC_OUT_EXT = 1000148007 + VK_BLEND_OP_DST_OUT_EXT = 1000148008 + VK_BLEND_OP_SRC_ATOP_EXT = 1000148009 + VK_BLEND_OP_DST_ATOP_EXT = 1000148010 + VK_BLEND_OP_XOR_EXT = 1000148011 + VK_BLEND_OP_MULTIPLY_EXT = 1000148012 + VK_BLEND_OP_SCREEN_EXT = 1000148013 + VK_BLEND_OP_OVERLAY_EXT = 1000148014 + VK_BLEND_OP_DARKEN_EXT = 1000148015 + VK_BLEND_OP_LIGHTEN_EXT = 1000148016 + VK_BLEND_OP_COLORDODGE_EXT = 1000148017 + VK_BLEND_OP_COLORBURN_EXT = 1000148018 + VK_BLEND_OP_HARDLIGHT_EXT = 1000148019 + VK_BLEND_OP_SOFTLIGHT_EXT = 1000148020 + VK_BLEND_OP_DIFFERENCE_EXT = 1000148021 + VK_BLEND_OP_EXCLUSION_EXT = 1000148022 + VK_BLEND_OP_INVERT_EXT = 1000148023 + VK_BLEND_OP_INVERT_RGB_EXT = 1000148024 + VK_BLEND_OP_LINEARDODGE_EXT = 1000148025 + VK_BLEND_OP_LINEARBURN_EXT = 1000148026 + VK_BLEND_OP_VIVIDLIGHT_EXT = 1000148027 + VK_BLEND_OP_LINEARLIGHT_EXT = 1000148028 + VK_BLEND_OP_PINLIGHT_EXT = 1000148029 + VK_BLEND_OP_HARDMIX_EXT = 1000148030 + VK_BLEND_OP_HSL_HUE_EXT = 1000148031 + VK_BLEND_OP_HSL_SATURATION_EXT = 1000148032 + VK_BLEND_OP_HSL_COLOR_EXT = 1000148033 + VK_BLEND_OP_HSL_LUMINOSITY_EXT = 1000148034 + VK_BLEND_OP_PLUS_EXT = 1000148035 + VK_BLEND_OP_PLUS_CLAMPED_EXT = 1000148036 + VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT = 1000148037 + VK_BLEND_OP_PLUS_DARKER_EXT = 1000148038 + VK_BLEND_OP_MINUS_EXT = 1000148039 + VK_BLEND_OP_MINUS_CLAMPED_EXT = 1000148040 + VK_BLEND_OP_CONTRAST_EXT = 1000148041 + VK_BLEND_OP_INVERT_OVG_EXT = 1000148042 + VK_BLEND_OP_RED_EXT = 1000148043 + VK_BLEND_OP_GREEN_EXT = 1000148044 + VK_BLEND_OP_BLUE_EXT = 1000148045 + VkStencilOp* {.size: sizeof(cint).} = enum + VK_STENCIL_OP_KEEP = 0 + VK_STENCIL_OP_ZERO = 1 + VK_STENCIL_OP_REPLACE = 2 + VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3 + VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4 + VK_STENCIL_OP_INVERT = 5 + VK_STENCIL_OP_INCREMENT_AND_WRAP = 6 + VK_STENCIL_OP_DECREMENT_AND_WRAP = 7 + VkLogicOp* {.size: sizeof(cint).} = enum + VK_LOGIC_OP_CLEAR = 0 + VK_LOGIC_OP_AND = 1 + VK_LOGIC_OP_AND_REVERSE = 2 + VK_LOGIC_OP_COPY = 3 + VK_LOGIC_OP_AND_INVERTED = 4 + VK_LOGIC_OP_NO_OP = 5 + VK_LOGIC_OP_XOR = 6 + VK_LOGIC_OP_OR = 7 + VK_LOGIC_OP_NOR = 8 + VK_LOGIC_OP_EQUIVALENT = 9 + VK_LOGIC_OP_INVERT = 10 + VK_LOGIC_OP_OR_REVERSE = 11 + VK_LOGIC_OP_COPY_INVERTED = 12 + VK_LOGIC_OP_OR_INVERTED = 13 + VK_LOGIC_OP_NAND = 14 + VK_LOGIC_OP_SET = 15 + VkInternalAllocationType* {.size: sizeof(cint).} = enum + VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0 + VkSystemAllocationScope* {.size: sizeof(cint).} = enum + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0 + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1 + VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2 + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3 + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4 + VkPhysicalDeviceType* {.size: sizeof(cint).} = enum + VK_PHYSICAL_DEVICE_TYPE_OTHER = 0 + VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1 + VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2 + VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3 + VK_PHYSICAL_DEVICE_TYPE_CPU = 4 + VkVertexInputRate* {.size: sizeof(cint).} = enum + VK_VERTEX_INPUT_RATE_VERTEX = 0 + VK_VERTEX_INPUT_RATE_INSTANCE = 1 + VkFormat* {.size: sizeof(cint).} = enum + VK_FORMAT_UNDEFINED = 0 + VK_FORMAT_R4G4_UNORM_PACK8 = 1 + VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2 + VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3 + VK_FORMAT_R5G6B5_UNORM_PACK16 = 4 + VK_FORMAT_B5G6R5_UNORM_PACK16 = 5 + VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6 + VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7 + VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8 + VK_FORMAT_R8_UNORM = 9 + VK_FORMAT_R8_SNORM = 10 + VK_FORMAT_R8_USCALED = 11 + VK_FORMAT_R8_SSCALED = 12 + VK_FORMAT_R8_UINT = 13 + VK_FORMAT_R8_SINT = 14 + VK_FORMAT_R8_SRGB = 15 + VK_FORMAT_R8G8_UNORM = 16 + VK_FORMAT_R8G8_SNORM = 17 + VK_FORMAT_R8G8_USCALED = 18 + VK_FORMAT_R8G8_SSCALED = 19 + VK_FORMAT_R8G8_UINT = 20 + VK_FORMAT_R8G8_SINT = 21 + VK_FORMAT_R8G8_SRGB = 22 + VK_FORMAT_R8G8B8_UNORM = 23 + VK_FORMAT_R8G8B8_SNORM = 24 + VK_FORMAT_R8G8B8_USCALED = 25 + VK_FORMAT_R8G8B8_SSCALED = 26 + VK_FORMAT_R8G8B8_UINT = 27 + VK_FORMAT_R8G8B8_SINT = 28 + VK_FORMAT_R8G8B8_SRGB = 29 + VK_FORMAT_B8G8R8_UNORM = 30 + VK_FORMAT_B8G8R8_SNORM = 31 + VK_FORMAT_B8G8R8_USCALED = 32 + VK_FORMAT_B8G8R8_SSCALED = 33 + VK_FORMAT_B8G8R8_UINT = 34 + VK_FORMAT_B8G8R8_SINT = 35 + VK_FORMAT_B8G8R8_SRGB = 36 + VK_FORMAT_R8G8B8A8_UNORM = 37 + VK_FORMAT_R8G8B8A8_SNORM = 38 + VK_FORMAT_R8G8B8A8_USCALED = 39 + VK_FORMAT_R8G8B8A8_SSCALED = 40 + VK_FORMAT_R8G8B8A8_UINT = 41 + VK_FORMAT_R8G8B8A8_SINT = 42 + VK_FORMAT_R8G8B8A8_SRGB = 43 + VK_FORMAT_B8G8R8A8_UNORM = 44 + VK_FORMAT_B8G8R8A8_SNORM = 45 + VK_FORMAT_B8G8R8A8_USCALED = 46 + VK_FORMAT_B8G8R8A8_SSCALED = 47 + VK_FORMAT_B8G8R8A8_UINT = 48 + VK_FORMAT_B8G8R8A8_SINT = 49 + VK_FORMAT_B8G8R8A8_SRGB = 50 + VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51 + VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52 + VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53 + VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54 + VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55 + VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56 + VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57 + VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58 + VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59 + VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60 + VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61 + VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62 + VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63 + VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64 + VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65 + VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66 + VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67 + VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68 + VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69 + VK_FORMAT_R16_UNORM = 70 + VK_FORMAT_R16_SNORM = 71 + VK_FORMAT_R16_USCALED = 72 + VK_FORMAT_R16_SSCALED = 73 + VK_FORMAT_R16_UINT = 74 + VK_FORMAT_R16_SINT = 75 + VK_FORMAT_R16_SFLOAT = 76 + VK_FORMAT_R16G16_UNORM = 77 + VK_FORMAT_R16G16_SNORM = 78 + VK_FORMAT_R16G16_USCALED = 79 + VK_FORMAT_R16G16_SSCALED = 80 + VK_FORMAT_R16G16_UINT = 81 + VK_FORMAT_R16G16_SINT = 82 + VK_FORMAT_R16G16_SFLOAT = 83 + VK_FORMAT_R16G16B16_UNORM = 84 + VK_FORMAT_R16G16B16_SNORM = 85 + VK_FORMAT_R16G16B16_USCALED = 86 + VK_FORMAT_R16G16B16_SSCALED = 87 + VK_FORMAT_R16G16B16_UINT = 88 + VK_FORMAT_R16G16B16_SINT = 89 + VK_FORMAT_R16G16B16_SFLOAT = 90 + VK_FORMAT_R16G16B16A16_UNORM = 91 + VK_FORMAT_R16G16B16A16_SNORM = 92 + VK_FORMAT_R16G16B16A16_USCALED = 93 + VK_FORMAT_R16G16B16A16_SSCALED = 94 + VK_FORMAT_R16G16B16A16_UINT = 95 + VK_FORMAT_R16G16B16A16_SINT = 96 + VK_FORMAT_R16G16B16A16_SFLOAT = 97 + VK_FORMAT_R32_UINT = 98 + VK_FORMAT_R32_SINT = 99 + VK_FORMAT_R32_SFLOAT = 100 + VK_FORMAT_R32G32_UINT = 101 + VK_FORMAT_R32G32_SINT = 102 + VK_FORMAT_R32G32_SFLOAT = 103 + VK_FORMAT_R32G32B32_UINT = 104 + VK_FORMAT_R32G32B32_SINT = 105 + VK_FORMAT_R32G32B32_SFLOAT = 106 + VK_FORMAT_R32G32B32A32_UINT = 107 + VK_FORMAT_R32G32B32A32_SINT = 108 + VK_FORMAT_R32G32B32A32_SFLOAT = 109 + VK_FORMAT_R64_UINT = 110 + VK_FORMAT_R64_SINT = 111 + VK_FORMAT_R64_SFLOAT = 112 + VK_FORMAT_R64G64_UINT = 113 + VK_FORMAT_R64G64_SINT = 114 + VK_FORMAT_R64G64_SFLOAT = 115 + VK_FORMAT_R64G64B64_UINT = 116 + VK_FORMAT_R64G64B64_SINT = 117 + VK_FORMAT_R64G64B64_SFLOAT = 118 + VK_FORMAT_R64G64B64A64_UINT = 119 + VK_FORMAT_R64G64B64A64_SINT = 120 + VK_FORMAT_R64G64B64A64_SFLOAT = 121 + VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122 + VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123 + VK_FORMAT_D16_UNORM = 124 + VK_FORMAT_X8_D24_UNORM_PACK32 = 125 + VK_FORMAT_D32_SFLOAT = 126 + VK_FORMAT_S8_UINT = 127 + VK_FORMAT_D16_UNORM_S8_UINT = 128 + VK_FORMAT_D24_UNORM_S8_UINT = 129 + VK_FORMAT_D32_SFLOAT_S8_UINT = 130 + VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131 + VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132 + VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133 + VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134 + VK_FORMAT_BC2_UNORM_BLOCK = 135 + VK_FORMAT_BC2_SRGB_BLOCK = 136 + VK_FORMAT_BC3_UNORM_BLOCK = 137 + VK_FORMAT_BC3_SRGB_BLOCK = 138 + VK_FORMAT_BC4_UNORM_BLOCK = 139 + VK_FORMAT_BC4_SNORM_BLOCK = 140 + VK_FORMAT_BC5_UNORM_BLOCK = 141 + VK_FORMAT_BC5_SNORM_BLOCK = 142 + VK_FORMAT_BC6H_UFLOAT_BLOCK = 143 + VK_FORMAT_BC6H_SFLOAT_BLOCK = 144 + VK_FORMAT_BC7_UNORM_BLOCK = 145 + VK_FORMAT_BC7_SRGB_BLOCK = 146 + VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147 + VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148 + VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149 + VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150 + VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151 + VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152 + VK_FORMAT_EAC_R11_UNORM_BLOCK = 153 + VK_FORMAT_EAC_R11_SNORM_BLOCK = 154 + VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155 + VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156 + VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157 + VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158 + VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159 + VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160 + VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161 + VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162 + VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163 + VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164 + VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165 + VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166 + VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167 + VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168 + VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169 + VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170 + VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171 + VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172 + VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173 + VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174 + VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175 + VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176 + VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177 + VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178 + VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179 + VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180 + VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181 + VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182 + VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183 + VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184 + VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000 + VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001 + VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002 + VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003 + VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004 + VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005 + VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006 + VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007 + VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK = 1000066000 + VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK = 1000066001 + VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK = 1000066002 + VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK = 1000066003 + VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK = 1000066004 + VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK = 1000066005 + VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK = 1000066006 + VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK = 1000066007 + VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK = 1000066008 + VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK = 1000066009 + VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK = 1000066010 + VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK = 1000066011 + VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK = 1000066012 + VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK = 1000066013 + VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000 + VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001 + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002 + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003 + VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004 + VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005 + VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006 + VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007 + VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008 + VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009 + VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010 + VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011 + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012 + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013 + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014 + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015 + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016 + VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017 + VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018 + VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019 + VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020 + VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021 + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022 + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023 + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024 + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025 + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026 + VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027 + VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028 + VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029 + VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030 + VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031 + VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032 + VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033 + VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT = 1000288000 + VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT = 1000288001 + VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT = 1000288002 + VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT = 1000288003 + VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT = 1000288004 + VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT = 1000288005 + VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT = 1000288006 + VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT = 1000288007 + VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT = 1000288008 + VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT = 1000288009 + VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT = 1000288010 + VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT = 1000288011 + VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT = 1000288012 + VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT = 1000288013 + VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT = 1000288014 + VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT = 1000288015 + VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT = 1000288016 + VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT = 1000288017 + VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT = 1000288018 + VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT = 1000288019 + VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT = 1000288020 + VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT = 1000288021 + VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT = 1000288022 + VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT = 1000288023 + VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT = 1000288024 + VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT = 1000288025 + VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT = 1000288026 + VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT = 1000288027 + VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT = 1000288028 + VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT = 1000288029 + VK_FORMAT_G8_B8R8_2PLANE_444_UNORM = 1000330000 + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16 = 1000330001 + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16 = 1000330002 + VK_FORMAT_G16_B16R16_2PLANE_444_UNORM = 1000330003 + VK_FORMAT_A4R4G4B4_UNORM_PACK16 = 1000340000 + VK_FORMAT_A4B4G4R4_UNORM_PACK16 = 1000340001 + VK_FORMAT_R16G16_S10_5_NV = 1000464000 + VkStructureType* {.size: sizeof(cint).} = enum + VK_STRUCTURE_TYPE_APPLICATION_INFO = 0 + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1 + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO = 2 + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 3 + VK_STRUCTURE_TYPE_SUBMIT_INFO = 4 + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 5 + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE = 6 + VK_STRUCTURE_TYPE_BIND_SPARSE_INFO = 7 + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO = 8 + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO = 9 + VK_STRUCTURE_TYPE_EVENT_CREATE_INFO = 10 + VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO = 11 + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 12 + VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO = 13 + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 14 + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO = 15 + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO = 16 + VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO = 17 + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO = 18 + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19 + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20 + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21 + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22 + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23 + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24 + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25 + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26 + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27 + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO = 28 + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO = 29 + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO = 30 + VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO = 31 + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32 + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO = 33 + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO = 34 + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET = 35 + VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET = 36 + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO = 37 + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO = 38 + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO = 39 + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO = 40 + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO = 41 + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO = 42 + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO = 43 + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER = 44 + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 45 + VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46 + VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47 + VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES = 50 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES = 51 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES = 52 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES = 53 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES = 54 + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000 + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001 + VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000 + VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001 + VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR = 1000003000 + VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000 + VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000 + VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000 + VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000 + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000 + VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID = 1000010000 + VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID = 1000010001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID = 1000010002 + VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000 + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000 + VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000 + VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001 + VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002 + VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR = 1000023000 + VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR = 1000023001 + VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR = 1000023002 + VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR = 1000023003 + VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR = 1000023004 + VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR = 1000023005 + VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000023006 + VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR = 1000023007 + VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR = 1000023008 + VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR = 1000023009 + VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR = 1000023010 + VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR = 1000023011 + VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR = 1000023012 + VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR = 1000023013 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR = 1000023014 + VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR = 1000023015 + VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR = 1000023016 + VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR = 1000024000 + VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR = 1000024001 + VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR = 1000024002 + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000 + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001 + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001 + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002 + VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX = 1000029000 + VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX = 1000029001 + VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX = 1000029002 + VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000 + VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT = 1000038000 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000038001 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000038002 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT = 1000038003 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT = 1000038004 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT = 1000038005 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT = 1000038006 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT = 1000038007 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT = 1000038008 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT = 1000038009 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT = 1000038010 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT = 1000039000 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000039001 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000039002 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT = 1000039003 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT = 1000039004 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT = 1000039005 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT = 1000039006 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT = 1000039007 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT = 1000039008 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT = 1000039009 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT = 1000039010 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR = 1000040000 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR = 1000040001 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR = 1000040003 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000040004 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR = 1000040005 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR = 1000040006 + VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000 + VK_STRUCTURE_TYPE_RENDERING_INFO = 1000044000 + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO = 1000044001 + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO = 1000044002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES = 1000044003 + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO = 1000044004 + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006 + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007 + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008 + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009 + VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000 + VK_STRUCTURE_TYPE_PRIVATE_VENDOR_INFO_RESERVED_OFFSET_0_NV = 1000051000 + VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002 + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000 + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001 + VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000 + VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001 + VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 = 1000059000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001 + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 = 1000059002 + VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 = 1000059003 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004 + VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 = 1000059005 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006 + VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008 + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO = 1000060000 + VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003 + VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004 + VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO = 1000060005 + VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006 + VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007 + VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR = 1000060008 + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR = 1000060009 + VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR = 1000060010 + VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011 + VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012 + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013 + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014 + VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000 + VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000 + VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001 + VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT = 1000068000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT = 1000068001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT = 1000068002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000 + VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000 + VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002 + VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES = 1000071003 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004 + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO = 1000072000 + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO = 1000072001 + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO = 1000072002 + VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000 + VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001 + VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002 + VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR = 1000073003 + VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR = 1000074000 + VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR = 1000074001 + VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR = 1000074002 + VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR = 1000075000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000 + VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001 + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO = 1000077000 + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000 + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001 + VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002 + VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR = 1000078003 + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000 + VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR = 1000079001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000 + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001 + VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000 + VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000 + VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000 + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000 + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000 + VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000 + VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT = 1000091001 + VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT = 1000091002 + VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003 + VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000 + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000 + VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000 + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT = 1000102000 + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT = 1000102001 + VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000 + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001 + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002 + VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003 + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 = 1000109000 + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2 = 1000109001 + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2 = 1000109002 + VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 = 1000109003 + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2 = 1000109004 + VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO = 1000109005 + VK_STRUCTURE_TYPE_SUBPASS_END_INFO = 1000109006 + VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000 + VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES = 1000112001 + VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO = 1000113000 + VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000 + VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001 + VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002 + VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR = 1000115000 + VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR = 1000115001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR = 1000116000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR = 1000116001 + VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR = 1000116002 + VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR = 1000116003 + VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR = 1000116004 + VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR = 1000116005 + VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR = 1000116006 + VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_RESERVATION_INFO_KHR = 1000116007 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000 + VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001 + VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002 + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000 + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001 + VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000 + VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR = 1000121000 + VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR = 1000121001 + VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR = 1000121002 + VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR = 1000121003 + VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR = 1000121004 + VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000 + VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000 + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000 + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001 + VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000 + VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT = 1000128001 + VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT = 1000128002 + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000128003 + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004 + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID = 1000129000 + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID = 1000129001 + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID = 1000129002 + VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003 + VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004 + VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005 + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID = 1000129006 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000 + VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES = 1000138000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES = 1000138001 + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK = 1000138002 + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO = 1000138003 + VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000 + VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001 + VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003 + VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT = 1000143004 + VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO = 1000145000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002 + VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 = 1000145003 + VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 = 1000146000 + VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 = 1000146001 + VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 = 1000146002 + VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 = 1000146003 + VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 = 1000146004 + VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001 + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002 + VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR = 1000150000 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR = 1000150002 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR = 1000150003 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR = 1000150004 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR = 1000150005 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR = 1000150006 + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000150007 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR = 1000150009 + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR = 1000150010 + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR = 1000150011 + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR = 1000150012 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR = 1000150013 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR = 1000150014 + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015 + VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017 + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR = 1000150020 + VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001 + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000 + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO = 1000156001 + VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002 + VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004 + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005 + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO = 1000157000 + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO = 1000157001 + VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT = 1000158000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT = 1000158002 + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003 + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004 + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005 + VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT = 1000158006 + VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000 + VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001 + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002 + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003 + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR = 1000163000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR = 1000163001 + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002 + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005 + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001 + VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003 + VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004 + VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005 + VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006 + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009 + VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV = 1000165012 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000 + VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000 + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT = 1000170000 + VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT = 1000170001 + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR = 1000174000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000 + VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000 + VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR = 1000181000 + VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD = 1000183000 + VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT = 1000184000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR = 1000187000 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000187001 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR = 1000187002 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR = 1000187003 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR = 1000187004 + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR = 1000187005 + VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000 + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002 + VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP = 1000191000 + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000 + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR = 1000203000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000 + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002 + VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000 + VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES = 1000207000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES = 1000207001 + VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO = 1000207002 + VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO = 1000207003 + VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO = 1000207004 + VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO = 1000207005 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL = 1000209000 + VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL = 1000210000 + VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL = 1000210001 + VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL = 1000210002 + VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL = 1000210003 + VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL = 1000210004 + VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL = 1000210005 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000 + VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD = 1000213000 + VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD = 1000213001 + VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000 + VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001 + VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES = 1000225000 + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO = 1000225001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES = 1000225002 + VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000226000 + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR = 1000226001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR = 1000226002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR = 1000226003 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR = 1000226004 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD = 1000227000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD = 1000229000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT = 1000234000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT = 1000237000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT = 1000238000 + VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT = 1000238001 + VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR = 1000239000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV = 1000240000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000 + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001 + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT = 1000244000 + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO = 1000244001 + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT = 1000244002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES = 1000245000 + VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000 + VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT = 1000247000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR = 1000248000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV = 1000249000 + VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV = 1000250000 + VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV = 1000250001 + VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV = 1000250002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT = 1000251000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT = 1000252000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT = 1000254000 + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT = 1000254001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT = 1000254002 + VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT = 1000255000 + VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT = 1000255001 + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT = 1000255002 + VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES = 1000257000 + VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002 + VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003 + VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT = 1000259000 + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = 1000259001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = 1000259002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT = 1000260000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = 1000265000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT = 1000267000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000 + VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR = 1000269001 + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002 + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR = 1000269003 + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004 + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000 + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT = 1000274000 + VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = 1000274001 + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT = 1000274002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT = 1000275000 + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT = 1000275001 + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT = 1000275002 + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT = 1000275003 + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT = 1000275004 + VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT = 1000275005 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000 + VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001 + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002 + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV = 1000277003 + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV = 1000277004 + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV = 1000277005 + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV = 1000277006 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV = 1000277007 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV = 1000278000 + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV = 1000278001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES = 1000280000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES = 1000280001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES = 1000281001 + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000 + VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000 + VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001 + VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = 1000286000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = 1000286001 + VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002 + VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV = 1000292000 + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_BARRIER_NV = 1000292001 + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_BARRIER_CREATE_INFO_NV = 1000292002 + VK_STRUCTURE_TYPE_PRESENT_ID_KHR = 1000294000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR = 1000294001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES = 1000295000 + VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO = 1000295001 + VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO = 1000295002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_SC_1_0_FEATURES = 1000298000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_SC_1_0_PROPERTIES = 1000298001 + VK_STRUCTURE_TYPE_DEVICE_OBJECT_RESERVATION_CREATE_INFO = 1000298002 + VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_RESERVATION_CREATE_INFO = 1000298003 + VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_CONSUMPTION = 1000298004 + VK_STRUCTURE_TYPE_PIPELINE_POOL_SIZE = 1000298005 + VK_STRUCTURE_TYPE_FAULT_DATA = 1000298007 + VK_STRUCTURE_TYPE_FAULT_CALLBACK_INFO = 1000298008 + VK_STRUCTURE_TYPE_PIPELINE_OFFLINE_CREATE_INFO = 1000298010 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR = 1000299000 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR = 1000299001 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR = 1000299002 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR = 1000299003 + VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR = 1000299004 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000 + VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001 + VK_STRUCTURE_TYPE_REFRESH_OBJECT_LIST_KHR = 1000308000 + VK_STRUCTURE_TYPE_RESERVED_QCOM = 1000309000 + VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT = 1000311000 + VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT = 1000311001 + VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT = 1000311002 + VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT = 1000311003 + VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT = 1000311004 + VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT = 1000311005 + VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT = 1000311006 + VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT = 1000311007 + VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT = 1000311008 + VK_STRUCTURE_TYPE_IMPORT_METAL_IO_SURFACE_INFO_EXT = 1000311009 + VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311010 + VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311011 + VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 = 1000314000 + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 = 1000314001 + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 = 1000314002 + VK_STRUCTURE_TYPE_DEPENDENCY_INFO = 1000314003 + VK_STRUCTURE_TYPE_SUBMIT_INFO_2 = 1000314004 + VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO = 1000314005 + VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO = 1000314006 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES = 1000314007 + VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008 + VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV = 1000314009 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT = 1000316000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_DENSITY_MAP_PROPERTIES_EXT = 1000316001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT = 1000316002 + VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT = 1000316003 + VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT = 1000316004 + VK_STRUCTURE_TYPE_BUFFER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316005 + VK_STRUCTURE_TYPE_IMAGE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316006 + VK_STRUCTURE_TYPE_IMAGE_VIEW_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316007 + VK_STRUCTURE_TYPE_SAMPLER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316008 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316009 + VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT = 1000316010 + VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT = 1000316011 + VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_PUSH_DESCRIPTOR_BUFFER_HANDLE_EXT = 1000316012 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT = 1000320000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT = 1000320001 + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT = 1000320002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD = 1000321000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR = 1000322000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR = 1000323000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV = 1000326000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV = 1000326001 + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV = 1000326002 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV = 1000327000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV = 1000327001 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV = 1000327002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT = 1000328000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT = 1000328001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT = 1000330000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT = 1000332000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT = 1000332001 + VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM = 1000333000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000 + VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 = 1000337000 + VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2 = 1000337001 + VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2 = 1000337002 + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2 = 1000337003 + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2 = 1000337004 + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2 = 1000337005 + VK_STRUCTURE_TYPE_BUFFER_COPY_2 = 1000337006 + VK_STRUCTURE_TYPE_IMAGE_COPY_2 = 1000337007 + VK_STRUCTURE_TYPE_IMAGE_BLIT_2 = 1000337008 + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2 = 1000337009 + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2 = 1000337010 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT = 1000338000 + VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT = 1000338001 + VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT = 1000338002 + VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT = 1000338003 + VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT = 1000338004 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT = 1000339000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT = 1000341000 + VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT = 1000341001 + VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT = 1000341002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT = 1000342000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT = 1000344000 + VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR = 1000347000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR = 1000347001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR = 1000348013 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT = 1000351000 + VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT = 1000351002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT = 1000352000 + VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT = 1000352001 + VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT = 1000352002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT = 1000353000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ADDRESS_BINDING_REPORT_FEATURES_EXT = 1000354000 + VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT = 1000354001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT = 1000355000 + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT = 1000355001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT = 1000356000 + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 = 1000360000 + VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364000 + VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA = 1000364001 + VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364002 + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365000 + VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365001 + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA = 1000366000 + VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA = 1000366001 + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA = 1000366002 + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA = 1000366003 + VK_STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA = 1000366004 + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA = 1000366005 + VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA = 1000366006 + VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA = 1000366007 + VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA = 1000366008 + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA = 1000366009 + VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI = 1000369000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI = 1000369001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI = 1000369002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI = 1000370000 + VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV = 1000371000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV = 1000371001 + VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT = 1000372000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT = 1000372001 + VK_STRUCTURE_TYPE_IMPORT_FENCE_SCI_SYNC_INFO_NV = 1000373000 + VK_STRUCTURE_TYPE_EXPORT_FENCE_SCI_SYNC_INFO_NV = 1000373001 + VK_STRUCTURE_TYPE_FENCE_GET_SCI_SYNC_INFO_NV = 1000373002 + VK_STRUCTURE_TYPE_SCI_SYNC_ATTRIBUTES_INFO_NV = 1000373003 + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_SCI_SYNC_INFO_NV = 1000373004 + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_SCI_SYNC_INFO_NV = 1000373005 + VK_STRUCTURE_TYPE_SEMAPHORE_GET_SCI_SYNC_INFO_NV = 1000373006 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SCI_SYNC_FEATURES_NV = 1000373007 + VK_STRUCTURE_TYPE_IMPORT_MEMORY_SCI_BUF_INFO_NV = 1000374000 + VK_STRUCTURE_TYPE_EXPORT_MEMORY_SCI_BUF_INFO_NV = 1000374001 + VK_STRUCTURE_TYPE_MEMORY_GET_SCI_BUF_INFO_NV = 1000374002 + VK_STRUCTURE_TYPE_MEMORY_SCI_BUF_PROPERTIES_NV = 1000374003 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCI_BUF_FEATURES_NV = 1000374004 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT = 1000376000 + VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT = 1000376001 + VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT = 1000376002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT = 1000377000 + VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX = 1000378000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT = 1000381000 + VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT = 1000381001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT = 1000382000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR = 1000386000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR = 1000388000 + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR = 1000388001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT = 1000391000 + VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT = 1000391001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT = 1000393000 + VK_STRUCTURE_TYPE_MICROMAP_BUILD_INFO_EXT = 1000396000 + VK_STRUCTURE_TYPE_MICROMAP_VERSION_INFO_EXT = 1000396001 + VK_STRUCTURE_TYPE_COPY_MICROMAP_INFO_EXT = 1000396002 + VK_STRUCTURE_TYPE_COPY_MICROMAP_TO_MEMORY_INFO_EXT = 1000396003 + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_MICROMAP_INFO_EXT = 1000396004 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_EXT = 1000396005 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT = 1000396006 + VK_STRUCTURE_TYPE_MICROMAP_CREATE_INFO_EXT = 1000396007 + VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT = 1000396008 + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT = 1000396009 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI = 1000404000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI = 1000404001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000 + VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES = 1000413000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 1000413001 + VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS = 1000413002 + VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS = 1000413003 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM = 1000415000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT = 1000418000 + VK_STRUCTURE_TYPE_IMAGE_VIEW_SLICED_CREATE_INFO_EXT = 1000418001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000 + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001 + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = 1000421000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT = 1000422000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM = 1000425000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM = 1000425001 + VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM = 1000425002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV = 1000426000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV = 1000426001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV = 1000427000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV = 1000427001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV = 1000430000 + VK_STRUCTURE_TYPE_APPLICATION_PARAMETERS_EXT = 1000435000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT = 1000437000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM = 1000440000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM = 1000440001 + VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM = 1000440002 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT = 1000455000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT = 1000455001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT = 1000458000 + VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT = 1000458001 + VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000458002 + VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT = 1000458003 + VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG = 1000459000 + VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG = 1000459001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT = 1000462000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT = 1000462001 + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT = 1000462002 + VK_STRUCTURE_TYPE_SHADER_MODULE_IDENTIFIER_EXT = 1000462003 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV = 1000464000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV = 1000464001 + VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV = 1000464002 + VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV = 1000464003 + VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_INFO_NV = 1000464004 + VK_STRUCTURE_TYPE_OPTICAL_FLOW_EXECUTE_INFO_NV = 1000464005 + VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV = 1000464010 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT = 1000465000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = 1000466000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM = 1000484000 + VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM = 1000484001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC = 1000485000 + VK_STRUCTURE_TYPE_AMIGO_PROFILING_SUBMIT_INFO_SEC = 1000485001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM = 1000488000 + VK_STRUCTURE_TYPE_SEMAPHORE_SCI_SYNC_POOL_CREATE_INFO_NV = 1000489000 + VK_STRUCTURE_TYPE_SEMAPHORE_SCI_SYNC_CREATE_INFO_NV = 1000489001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SCI_SYNC_2_FEATURES_NV = 1000489002 + VK_STRUCTURE_TYPE_DEVICE_SEMAPHORE_SCI_SYNC_POOL_RESERVATION_CREATE_INFO_NV = 1000489003 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV = 1000490000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV = 1000490001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM = 1000497000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM = 1000497001 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT = 1000498000 + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM = 1000510000 + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM = 1000510001 + VkSubpassContents* {.size: sizeof(cint).} = enum + VK_SUBPASS_CONTENTS_INLINE = 0 + VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1 + VkResult* {.size: sizeof(cint).} = enum + VK_ERROR_COMPRESSION_EXHAUSTED_EXT = -1000338000 + VK_ERROR_NO_PIPELINE_MATCH = -1000298001 + VK_ERROR_INVALID_PIPELINE_CACHE_DATA = -1000298000 + VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000 + VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000 + VK_ERROR_NOT_PERMITTED_KHR = -1000174001 + VK_ERROR_FRAGMENTATION = -1000161000 + VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000 + VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003 + VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000 + VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR = -1000023005 + VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR = -1000023004 + VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR = -1000023003 + VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR = -1000023002 + VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR = -1000023001 + VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR = -1000023000 + VK_ERROR_INVALID_SHADER_NV = -1000012000 + VK_ERROR_VALIDATION_FAILED_EXT = -1000011001 + VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001 + VK_ERROR_OUT_OF_DATE_KHR = -1000001004 + VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001 + VK_ERROR_SURFACE_LOST_KHR = -1000000000 + VK_ERROR_UNKNOWN = -13 + VK_ERROR_FRAGMENTED_POOL = -12 + VK_ERROR_FORMAT_NOT_SUPPORTED = -11 + VK_ERROR_TOO_MANY_OBJECTS = -10 + VK_ERROR_INCOMPATIBLE_DRIVER = -9 + VK_ERROR_FEATURE_NOT_PRESENT = -8 + VK_ERROR_EXTENSION_NOT_PRESENT = -7 + VK_ERROR_LAYER_NOT_PRESENT = -6 + VK_ERROR_MEMORY_MAP_FAILED = -5 + VK_ERROR_DEVICE_LOST = -4 + VK_ERROR_INITIALIZATION_FAILED = -3 + VK_ERROR_OUT_OF_DEVICE_MEMORY = -2 + VK_ERROR_OUT_OF_HOST_MEMORY = -1 + VK_SUCCESS = 0 + VK_NOT_READY = 1 + VK_TIMEOUT = 2 + VK_EVENT_SET = 3 + VK_EVENT_RESET = 4 + VK_INCOMPLETE = 5 + VK_SUBOPTIMAL_KHR = 1000001003 + VK_THREAD_IDLE_KHR = 1000268000 + VK_THREAD_DONE_KHR = 1000268001 + VK_OPERATION_DEFERRED_KHR = 1000268002 + VK_OPERATION_NOT_DEFERRED_KHR = 1000268003 + VK_PIPELINE_COMPILE_REQUIRED = 1000297000 + VkDynamicState* {.size: sizeof(cint).} = enum + VK_DYNAMIC_STATE_VIEWPORT = 0 + VK_DYNAMIC_STATE_SCISSOR = 1 + VK_DYNAMIC_STATE_LINE_WIDTH = 2 + VK_DYNAMIC_STATE_DEPTH_BIAS = 3 + VK_DYNAMIC_STATE_BLEND_CONSTANTS = 4 + VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5 + VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6 + VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7 + VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8 + VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000 + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000 + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT = 1000099001 + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT = 1000099002 + VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000 + VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004 + VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006 + VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV = 1000205000 + VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001 + VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR = 1000226000 + VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000 + VK_DYNAMIC_STATE_CULL_MODE = 1000267000 + VK_DYNAMIC_STATE_FRONT_FACE = 1000267001 + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY = 1000267002 + VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT = 1000267003 + VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT = 1000267004 + VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE = 1000267005 + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE = 1000267006 + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE = 1000267007 + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP = 1000267008 + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE = 1000267009 + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE = 1000267010 + VK_DYNAMIC_STATE_STENCIL_OP = 1000267011 + VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR = 1000347000 + VK_DYNAMIC_STATE_VERTEX_INPUT_EXT = 1000352000 + VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT = 1000377000 + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE = 1000377001 + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE = 1000377002 + VK_DYNAMIC_STATE_LOGIC_OP_EXT = 1000377003 + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE = 1000377004 + VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT = 1000381000 + VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT = 1000455002 + VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT = 1000455003 + VK_DYNAMIC_STATE_POLYGON_MODE_EXT = 1000455004 + VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT = 1000455005 + VK_DYNAMIC_STATE_SAMPLE_MASK_EXT = 1000455006 + VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT = 1000455007 + VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT = 1000455008 + VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT = 1000455009 + VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT = 1000455010 + VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT = 1000455011 + VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT = 1000455012 + VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT = 1000455013 + VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT = 1000455014 + VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT = 1000455015 + VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT = 1000455016 + VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT = 1000455017 + VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT = 1000455018 + VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT = 1000455019 + VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT = 1000455020 + VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT = 1000455021 + VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT = 1000455022 + VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV = 1000455023 + VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV = 1000455024 + VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV = 1000455025 + VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV = 1000455026 + VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV = 1000455027 + VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV = 1000455028 + VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV = 1000455029 + VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV = 1000455030 + VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV = 1000455031 + VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV = 1000455032 + VkDescriptorUpdateTemplateType* {.size: sizeof(cint).} = enum + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0 + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1 + VkObjectType* {.size: sizeof(cint).} = enum + VK_OBJECT_TYPE_UNKNOWN = 0 + VK_OBJECT_TYPE_INSTANCE = 1 + VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2 + VK_OBJECT_TYPE_DEVICE = 3 + VK_OBJECT_TYPE_QUEUE = 4 + VK_OBJECT_TYPE_SEMAPHORE = 5 + VK_OBJECT_TYPE_COMMAND_BUFFER = 6 + VK_OBJECT_TYPE_FENCE = 7 + VK_OBJECT_TYPE_DEVICE_MEMORY = 8 + VK_OBJECT_TYPE_BUFFER = 9 + VK_OBJECT_TYPE_IMAGE = 10 + VK_OBJECT_TYPE_EVENT = 11 + VK_OBJECT_TYPE_QUERY_POOL = 12 + VK_OBJECT_TYPE_BUFFER_VIEW = 13 + VK_OBJECT_TYPE_IMAGE_VIEW = 14 + VK_OBJECT_TYPE_SHADER_MODULE = 15 + VK_OBJECT_TYPE_PIPELINE_CACHE = 16 + VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17 + VK_OBJECT_TYPE_RENDER_PASS = 18 + VK_OBJECT_TYPE_PIPELINE = 19 + VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20 + VK_OBJECT_TYPE_SAMPLER = 21 + VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22 + VK_OBJECT_TYPE_DESCRIPTOR_SET = 23 + VK_OBJECT_TYPE_FRAMEBUFFER = 24 + VK_OBJECT_TYPE_COMMAND_POOL = 25 + VK_OBJECT_TYPE_SURFACE_KHR = 1000000000 + VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000 + VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000 + VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001 + VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000 + VK_OBJECT_TYPE_VIDEO_SESSION_KHR = 1000023000 + VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR = 1000023001 + VK_OBJECT_TYPE_CU_MODULE_NVX = 1000029000 + VK_OBJECT_TYPE_CU_FUNCTION_NVX = 1000029001 + VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000 + VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000 + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000 + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000 + VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000 + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000 + VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000 + VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR = 1000268000 + VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV = 1000277000 + VK_OBJECT_TYPE_PRIVATE_DATA_SLOT = 1000295000 + VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = 1000366000 + VK_OBJECT_TYPE_MICROMAP_EXT = 1000396000 + VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV = 1000464000 + VK_OBJECT_TYPE_SEMAPHORE_SCI_SYNC_POOL_NV = 1000489000 + VkRayTracingInvocationReorderModeNV* {.size: sizeof(cint).} = enum + VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_NV = 0 + VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_NV = 1 + VkDirectDriverLoadingModeLUNARG* {.size: sizeof(cint).} = enum + VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG = 0 + VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG = 1 + VkQueueFlagBits* {.size: sizeof(cint).} = enum + VK_QUEUE_GRAPHICS_BIT = 0b00000000000000000000000000000001 + VK_QUEUE_COMPUTE_BIT = 0b00000000000000000000000000000010 + VK_QUEUE_TRANSFER_BIT = 0b00000000000000000000000000000100 + VK_QUEUE_SPARSE_BINDING_BIT = 0b00000000000000000000000000001000 + VK_QUEUE_PROTECTED_BIT = 0b00000000000000000000000000010000 + VK_QUEUE_VIDEO_DECODE_BIT_KHR = 0b00000000000000000000000000100000 + VK_QUEUE_VIDEO_ENCODE_BIT_KHR = 0b00000000000000000000000001000000 + VK_QUEUE_RESERVED_7_BIT_QCOM = 0b00000000000000000000000010000000 + VK_QUEUE_OPTICAL_FLOW_BIT_NV = 0b00000000000000000000000100000000 + VK_QUEUE_RESERVED_9_BIT_EXT = 0b00000000000000000000001000000000 +func toBits*(flags: openArray[VkQueueFlagBits]): VkQueueFlags = + for flag in flags: + result = VkQueueFlags(uint(result) or uint(flag)) +func toEnums*(number: VkQueueFlags): seq[VkQueueFlagBits] = + for value in VkQueueFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkQueueFlags): bool = cint(a) == cint(b) +type + VkCullModeFlagBits* {.size: sizeof(cint).} = enum + VK_CULL_MODE_FRONT_BIT = 0b00000000000000000000000000000001 + VK_CULL_MODE_BACK_BIT = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkCullModeFlagBits]): VkCullModeFlags = + for flag in flags: + result = VkCullModeFlags(uint(result) or uint(flag)) +func toEnums*(number: VkCullModeFlags): seq[VkCullModeFlagBits] = + for value in VkCullModeFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkCullModeFlags): bool = cint(a) == cint(b) +const + VK_CULL_MODE_NONE* = 0 + VK_CULL_MODE_FRONT_AND_BACK* = 0x00000003 +type + VkRenderPassCreateFlagBits* {.size: sizeof(cint).} = enum + VK_RENDER_PASS_CREATE_RESERVED_0_BIT_KHR = 0b00000000000000000000000000000001 + VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkRenderPassCreateFlagBits]): VkRenderPassCreateFlags = + for flag in flags: + result = VkRenderPassCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkRenderPassCreateFlags): seq[VkRenderPassCreateFlagBits] = + for value in VkRenderPassCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkRenderPassCreateFlags): bool = cint(a) == cint(b) +type + VkDeviceQueueCreateFlagBits* {.size: sizeof(cint).} = enum + VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 0b00000000000000000000000000000001 + VK_DEVICE_QUEUE_CREATE_RESERVED_1_BIT_QCOM = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkDeviceQueueCreateFlagBits]): VkDeviceQueueCreateFlags = + for flag in flags: + result = VkDeviceQueueCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkDeviceQueueCreateFlags): seq[VkDeviceQueueCreateFlagBits] = + for value in VkDeviceQueueCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDeviceQueueCreateFlags): bool = cint(a) == cint(b) +type + VkMemoryPropertyFlagBits* {.size: sizeof(cint).} = enum + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0b00000000000000000000000000000001 + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0b00000000000000000000000000000010 + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0b00000000000000000000000000000100 + VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0b00000000000000000000000000001000 + VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0b00000000000000000000000000010000 + VK_MEMORY_PROPERTY_PROTECTED_BIT = 0b00000000000000000000000000100000 + VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD = 0b00000000000000000000000001000000 + VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD = 0b00000000000000000000000010000000 + VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV = 0b00000000000000000000000100000000 +func toBits*(flags: openArray[VkMemoryPropertyFlagBits]): VkMemoryPropertyFlags = + for flag in flags: + result = VkMemoryPropertyFlags(uint(result) or uint(flag)) +func toEnums*(number: VkMemoryPropertyFlags): seq[VkMemoryPropertyFlagBits] = + for value in VkMemoryPropertyFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkMemoryPropertyFlags): bool = cint(a) == cint(b) +type + VkMemoryHeapFlagBits* {.size: sizeof(cint).} = enum + VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0b00000000000000000000000000000001 + VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0b00000000000000000000000000000010 + VK_MEMORY_HEAP_SEU_SAFE_BIT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkMemoryHeapFlagBits]): VkMemoryHeapFlags = + for flag in flags: + result = VkMemoryHeapFlags(uint(result) or uint(flag)) +func toEnums*(number: VkMemoryHeapFlags): seq[VkMemoryHeapFlagBits] = + for value in VkMemoryHeapFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkMemoryHeapFlags): bool = cint(a) == cint(b) +type + VkAccessFlagBits* {.size: sizeof(cint).} = enum + VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0b00000000000000000000000000000001 + VK_ACCESS_INDEX_READ_BIT = 0b00000000000000000000000000000010 + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0b00000000000000000000000000000100 + VK_ACCESS_UNIFORM_READ_BIT = 0b00000000000000000000000000001000 + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0b00000000000000000000000000010000 + VK_ACCESS_SHADER_READ_BIT = 0b00000000000000000000000000100000 + VK_ACCESS_SHADER_WRITE_BIT = 0b00000000000000000000000001000000 + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0b00000000000000000000000010000000 + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0b00000000000000000000000100000000 + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0b00000000000000000000001000000000 + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0b00000000000000000000010000000000 + VK_ACCESS_TRANSFER_READ_BIT = 0b00000000000000000000100000000000 + VK_ACCESS_TRANSFER_WRITE_BIT = 0b00000000000000000001000000000000 + VK_ACCESS_HOST_READ_BIT = 0b00000000000000000010000000000000 + VK_ACCESS_HOST_WRITE_BIT = 0b00000000000000000100000000000000 + VK_ACCESS_MEMORY_READ_BIT = 0b00000000000000001000000000000000 + VK_ACCESS_MEMORY_WRITE_BIT = 0b00000000000000010000000000000000 + VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0b00000000000000100000000000000000 + VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0b00000000000001000000000000000000 + VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0b00000000000010000000000000000000 + VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0b00000000000100000000000000000000 + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0b00000000001000000000000000000000 + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0b00000000010000000000000000000000 + VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0b00000000100000000000000000000000 + VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0b00000001000000000000000000000000 + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0b00000010000000000000000000000000 + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0b00000100000000000000000000000000 + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0b00001000000000000000000000000000 +func toBits*(flags: openArray[VkAccessFlagBits]): VkAccessFlags = + for flag in flags: + result = VkAccessFlags(uint(result) or uint(flag)) +func toEnums*(number: VkAccessFlags): seq[VkAccessFlagBits] = + for value in VkAccessFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkAccessFlags): bool = cint(a) == cint(b) +type + VkBufferUsageFlagBits* {.size: sizeof(cint).} = enum + VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 0b00000000000000000000000000000001 + VK_BUFFER_USAGE_TRANSFER_DST_BIT = 0b00000000000000000000000000000010 + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0b00000000000000000000000000000100 + VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0b00000000000000000000000000001000 + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0b00000000000000000000000000010000 + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0b00000000000000000000000000100000 + VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0b00000000000000000000000001000000 + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0b00000000000000000000000010000000 + VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0b00000000000000000000000100000000 + VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0b00000000000000000000001000000000 + VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR = 0b00000000000000000000010000000000 + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0b00000000000000000000100000000000 + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0b00000000000000000001000000000000 + VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0b00000000000000000010000000000000 + VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0b00000000000000000100000000000000 + VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0b00000000000000001000000000000000 + VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0b00000000000000010000000000000000 + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT = 0b00000000000000100000000000000000 + VK_BUFFER_USAGE_RESERVED_18_BIT_QCOM = 0b00000000000001000000000000000000 + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0b00000000000010000000000000000000 + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0b00000000000100000000000000000000 + VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT = 0b00000000001000000000000000000000 + VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT = 0b00000000010000000000000000000000 + VK_BUFFER_USAGE_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT = 0b00000000100000000000000000000000 + VK_BUFFER_USAGE_MICROMAP_STORAGE_BIT_EXT = 0b00000001000000000000000000000000 + VK_BUFFER_USAGE_RESERVED_25_BIT_AMD = 0b00000010000000000000000000000000 + VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT = 0b00000100000000000000000000000000 +func toBits*(flags: openArray[VkBufferUsageFlagBits]): VkBufferUsageFlags = + for flag in flags: + result = VkBufferUsageFlags(uint(result) or uint(flag)) +func toEnums*(number: VkBufferUsageFlags): seq[VkBufferUsageFlagBits] = + for value in VkBufferUsageFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkBufferUsageFlags): bool = cint(a) == cint(b) +type + VkBufferCreateFlagBits* {.size: sizeof(cint).} = enum + VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0b00000000000000000000000000000001 + VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0b00000000000000000000000000000010 + VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0b00000000000000000000000000000100 + VK_BUFFER_CREATE_PROTECTED_BIT = 0b00000000000000000000000000001000 + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0b00000000000000000000000000010000 + VK_BUFFER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000000000000000100000 +func toBits*(flags: openArray[VkBufferCreateFlagBits]): VkBufferCreateFlags = + for flag in flags: + result = VkBufferCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkBufferCreateFlags): seq[VkBufferCreateFlagBits] = + for value in VkBufferCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkBufferCreateFlags): bool = cint(a) == cint(b) +type + VkShaderStageFlagBits* {.size: sizeof(cint).} = enum + VK_SHADER_STAGE_VERTEX_BIT = 0b00000000000000000000000000000001 + VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0b00000000000000000000000000000010 + VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0b00000000000000000000000000000100 + VK_SHADER_STAGE_GEOMETRY_BIT = 0b00000000000000000000000000001000 + VK_SHADER_STAGE_FRAGMENT_BIT = 0b00000000000000000000000000010000 + VK_SHADER_STAGE_COMPUTE_BIT = 0b00000000000000000000000000100000 + VK_SHADER_STAGE_TASK_BIT_EXT = 0b00000000000000000000000001000000 + VK_SHADER_STAGE_MESH_BIT_EXT = 0b00000000000000000000000010000000 + VK_SHADER_STAGE_RAYGEN_BIT_KHR = 0b00000000000000000000000100000000 + VK_SHADER_STAGE_ANY_HIT_BIT_KHR = 0b00000000000000000000001000000000 + VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0b00000000000000000000010000000000 + VK_SHADER_STAGE_MISS_BIT_KHR = 0b00000000000000000000100000000000 + VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0b00000000000000000001000000000000 + VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0b00000000000000000010000000000000 + VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI = 0b00000000000000000100000000000000 + VK_SHADER_STAGE_EXT_483_RESERVE_15 = 0b00000000000000001000000000000000 + VK_SHADER_STAGE_EXT_483_RESERVE_16 = 0b00000000000000010000000000000000 + VK_SHADER_STAGE_EXT_483_RESERVE_17 = 0b00000000000000100000000000000000 + VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI = 0b00000000000010000000000000000000 +func toBits*(flags: openArray[VkShaderStageFlagBits]): VkShaderStageFlags = + for flag in flags: + result = VkShaderStageFlags(uint(result) or uint(flag)) +func toEnums*(number: VkShaderStageFlags): seq[VkShaderStageFlagBits] = + for value in VkShaderStageFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkShaderStageFlags): bool = cint(a) == cint(b) +const + VK_SHADER_STAGE_ALL_GRAPHICS* = 0x0000001F + VK_SHADER_STAGE_ALL* = 0x7FFFFFFF +type + VkImageUsageFlagBits* {.size: sizeof(cint).} = enum + VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0b00000000000000000000000000000001 + VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0b00000000000000000000000000000010 + VK_IMAGE_USAGE_SAMPLED_BIT = 0b00000000000000000000000000000100 + VK_IMAGE_USAGE_STORAGE_BIT = 0b00000000000000000000000000001000 + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0b00000000000000000000000000010000 + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0b00000000000000000000000000100000 + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0b00000000000000000000000001000000 + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0b00000000000000000000000010000000 + VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b00000000000000000000000100000000 + VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0b00000000000000000000001000000000 + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0b00000000000000000000010000000000 + VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0b00000000000000000000100000000000 + VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR = 0b00000000000000000001000000000000 + VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0b00000000000000000010000000000000 + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0b00000000000000000100000000000000 + VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR = 0b00000000000000001000000000000000 + VK_IMAGE_USAGE_RESERVED_16_BIT_QCOM = 0b00000000000000010000000000000000 + VK_IMAGE_USAGE_RESERVED_17_BIT_QCOM = 0b00000000000000100000000000000000 + VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI = 0b00000000000001000000000000000000 + VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0b00000000000010000000000000000000 + VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM = 0b00000000000100000000000000000000 + VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM = 0b00000000001000000000000000000000 + VK_IMAGE_USAGE_RESERVED_22_BIT_EXT = 0b00000000010000000000000000000000 +func toBits*(flags: openArray[VkImageUsageFlagBits]): VkImageUsageFlags = + for flag in flags: + result = VkImageUsageFlags(uint(result) or uint(flag)) +func toEnums*(number: VkImageUsageFlags): seq[VkImageUsageFlagBits] = + for value in VkImageUsageFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkImageUsageFlags): bool = cint(a) == cint(b) +type + VkImageCreateFlagBits* {.size: sizeof(cint).} = enum + VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0b00000000000000000000000000000001 + VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0b00000000000000000000000000000010 + VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0b00000000000000000000000000000100 + VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0b00000000000000000000000000001000 + VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0b00000000000000000000000000010000 + VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT = 0b00000000000000000000000000100000 + VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT = 0b00000000000000000000000001000000 + VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 0b00000000000000000000000010000000 + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0b00000000000000000000000100000000 + VK_IMAGE_CREATE_DISJOINT_BIT = 0b00000000000000000000001000000000 + VK_IMAGE_CREATE_ALIAS_BIT = 0b00000000000000000000010000000000 + VK_IMAGE_CREATE_PROTECTED_BIT = 0b00000000000000000000100000000000 + VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0b00000000000000000001000000000000 + VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0b00000000000000000010000000000000 + VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT = 0b00000000000000000100000000000000 + VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM = 0b00000000000000001000000000000000 + VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000010000000000000000 + VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT = 0b00000000000000100000000000000000 + VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT = 0b00000000000001000000000000000000 + VK_IMAGE_CREATE_RESERVED_19_BIT_EXT = 0b00000000000010000000000000000000 +func toBits*(flags: openArray[VkImageCreateFlagBits]): VkImageCreateFlags = + for flag in flags: + result = VkImageCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkImageCreateFlags): seq[VkImageCreateFlagBits] = + for value in VkImageCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkImageCreateFlags): bool = cint(a) == cint(b) +type + VkImageViewCreateFlagBits* {.size: sizeof(cint).} = enum + VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0b00000000000000000000000000000001 + VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT = 0b00000000000000000000000000000010 + VK_IMAGE_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkImageViewCreateFlagBits]): VkImageViewCreateFlags = + for flag in flags: + result = VkImageViewCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkImageViewCreateFlags): seq[VkImageViewCreateFlagBits] = + for value in VkImageViewCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkImageViewCreateFlags): bool = cint(a) == cint(b) +type + VkSamplerCreateFlagBits* {.size: sizeof(cint).} = enum + VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0b00000000000000000000000000000001 + VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0b00000000000000000000000000000010 + VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT = 0b00000000000000000000000000000100 + VK_SAMPLER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000000000000000001000 + VK_SAMPLER_CREATE_IMAGE_PROCESSING_BIT_QCOM = 0b00000000000000000000000000010000 +func toBits*(flags: openArray[VkSamplerCreateFlagBits]): VkSamplerCreateFlags = + for flag in flags: + result = VkSamplerCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkSamplerCreateFlags): seq[VkSamplerCreateFlagBits] = + for value in VkSamplerCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSamplerCreateFlags): bool = cint(a) == cint(b) +type + VkPipelineCreateFlagBits* {.size: sizeof(cint).} = enum + VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0b00000000000000000000000000000001 + VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0b00000000000000000000000000000010 + VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0b00000000000000000000000000000100 + VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0b00000000000000000000000000001000 + VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0b00000000000000000000000000010000 + VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0b00000000000000000000000000100000 + VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR = 0b00000000000000000000000001000000 + VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0b00000000000000000000000010000000 + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT = 0b00000000000000000000000100000000 + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT = 0b00000000000000000000001000000000 + VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT = 0b00000000000000000000010000000000 + VK_PIPELINE_CREATE_LIBRARY_BIT_KHR = 0b00000000000000000000100000000000 + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0b00000000000000000001000000000000 + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0b00000000000000000010000000000000 + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0b00000000000000000100000000000000 + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0b00000000000000001000000000000000 + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0b00000000000000010000000000000000 + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0b00000000000000100000000000000000 + VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV = 0b00000000000001000000000000000000 + VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 0b00000000000010000000000000000000 + VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0b00000000000100000000000000000000 + VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b00000000001000000000000000000000 + VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0b00000000010000000000000000000000 + VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT = 0b00000000100000000000000000000000 + VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0b00000001000000000000000000000000 + VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0b00000010000000000000000000000000 + VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0b00000100000000000000000000000000 + VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT = 0b00001000000000000000000000000000 + VK_PIPELINE_CREATE_RESERVED_BIT_28_NV = 0b00010000000000000000000000000000 + VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT = 0b00100000000000000000000000000000 + VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT = 0b01000000000000000000000000000000 +func toBits*(flags: openArray[VkPipelineCreateFlagBits]): VkPipelineCreateFlags = + for flag in flags: + result = VkPipelineCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkPipelineCreateFlags): seq[VkPipelineCreateFlagBits] = + for value in VkPipelineCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPipelineCreateFlags): bool = cint(a) == cint(b) +type + VkPipelineShaderStageCreateFlagBits* {.size: sizeof(cint).} = enum + VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT = 0b00000000000000000000000000000001 + VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT = 0b00000000000000000000000000000010 + VK_PIPELINE_SHADER_STAGE_CREATE_RESERVED_3_BIT_KHR = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkPipelineShaderStageCreateFlagBits]): VkPipelineShaderStageCreateFlags = + for flag in flags: + result = VkPipelineShaderStageCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkPipelineShaderStageCreateFlags): seq[VkPipelineShaderStageCreateFlagBits] = + for value in VkPipelineShaderStageCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPipelineShaderStageCreateFlags): bool = cint(a) == cint(b) +type + VkColorComponentFlagBits* {.size: sizeof(cint).} = enum + VK_COLOR_COMPONENT_R_BIT = 0b00000000000000000000000000000001 + VK_COLOR_COMPONENT_G_BIT = 0b00000000000000000000000000000010 + VK_COLOR_COMPONENT_B_BIT = 0b00000000000000000000000000000100 + VK_COLOR_COMPONENT_A_BIT = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkColorComponentFlagBits]): VkColorComponentFlags = + for flag in flags: + result = VkColorComponentFlags(uint(result) or uint(flag)) +func toEnums*(number: VkColorComponentFlags): seq[VkColorComponentFlagBits] = + for value in VkColorComponentFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkColorComponentFlags): bool = cint(a) == cint(b) +type + VkFenceCreateFlagBits* {.size: sizeof(cint).} = enum + VK_FENCE_CREATE_SIGNALED_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkFenceCreateFlagBits]): VkFenceCreateFlags = + for flag in flags: + result = VkFenceCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkFenceCreateFlags): seq[VkFenceCreateFlagBits] = + for value in VkFenceCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkFenceCreateFlags): bool = cint(a) == cint(b) +type + VkFormatFeatureFlagBits* {.size: sizeof(cint).} = enum + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0b00000000000000000000000000000001 + VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0b00000000000000000000000000000010 + VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0b00000000000000000000000000000100 + VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0b00000000000000000000000000001000 + VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0b00000000000000000000000000010000 + VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0b00000000000000000000000000100000 + VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0b00000000000000000000000001000000 + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0b00000000000000000000000010000000 + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0b00000000000000000000000100000000 + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0b00000000000000000000001000000000 + VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0b00000000000000000000010000000000 + VK_FORMAT_FEATURE_BLIT_DST_BIT = 0b00000000000000000000100000000000 + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0b00000000000000000001000000000000 + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 0b00000000000000000010000000000000 + VK_FORMAT_FEATURE_TRANSFER_SRC_BIT = 0b00000000000000000100000000000000 + VK_FORMAT_FEATURE_TRANSFER_DST_BIT = 0b00000000000000001000000000000000 + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0b00000000000000010000000000000000 + VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT = 0b00000000000000100000000000000000 + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0b00000000000001000000000000000000 + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0b00000000000010000000000000000000 + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0b00000000000100000000000000000000 + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0b00000000001000000000000000000000 + VK_FORMAT_FEATURE_DISJOINT_BIT = 0b00000000010000000000000000000000 + VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0b00000000100000000000000000000000 + VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0b00000001000000000000000000000000 + VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR = 0b00000010000000000000000000000000 + VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR = 0b00000100000000000000000000000000 + VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR = 0b00001000000000000000000000000000 + VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR = 0b00010000000000000000000000000000 + VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0b00100000000000000000000000000000 + VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b01000000000000000000000000000000 +func toBits*(flags: openArray[VkFormatFeatureFlagBits]): VkFormatFeatureFlags = + for flag in flags: + result = VkFormatFeatureFlags(uint(result) or uint(flag)) +func toEnums*(number: VkFormatFeatureFlags): seq[VkFormatFeatureFlagBits] = + for value in VkFormatFeatureFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkFormatFeatureFlags): bool = cint(a) == cint(b) +type + VkQueryControlFlagBits* {.size: sizeof(cint).} = enum + VK_QUERY_CONTROL_PRECISE_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkQueryControlFlagBits]): VkQueryControlFlags = + for flag in flags: + result = VkQueryControlFlags(uint(result) or uint(flag)) +func toEnums*(number: VkQueryControlFlags): seq[VkQueryControlFlagBits] = + for value in VkQueryControlFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkQueryControlFlags): bool = cint(a) == cint(b) +type + VkQueryResultFlagBits* {.size: sizeof(cint).} = enum + VK_QUERY_RESULT_64_BIT = 0b00000000000000000000000000000001 + VK_QUERY_RESULT_WAIT_BIT = 0b00000000000000000000000000000010 + VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0b00000000000000000000000000000100 + VK_QUERY_RESULT_PARTIAL_BIT = 0b00000000000000000000000000001000 + VK_QUERY_RESULT_WITH_STATUS_BIT_KHR = 0b00000000000000000000000000010000 +func toBits*(flags: openArray[VkQueryResultFlagBits]): VkQueryResultFlags = + for flag in flags: + result = VkQueryResultFlags(uint(result) or uint(flag)) +func toEnums*(number: VkQueryResultFlags): seq[VkQueryResultFlagBits] = + for value in VkQueryResultFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkQueryResultFlags): bool = cint(a) == cint(b) +type + VkCommandBufferUsageFlagBits* {.size: sizeof(cint).} = enum + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0b00000000000000000000000000000001 + VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0b00000000000000000000000000000010 + VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkCommandBufferUsageFlagBits]): VkCommandBufferUsageFlags = + for flag in flags: + result = VkCommandBufferUsageFlags(uint(result) or uint(flag)) +func toEnums*(number: VkCommandBufferUsageFlags): seq[VkCommandBufferUsageFlagBits] = + for value in VkCommandBufferUsageFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkCommandBufferUsageFlags): bool = cint(a) == cint(b) +type + VkQueryPipelineStatisticFlagBits* {.size: sizeof(cint).} = enum + VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0b00000000000000000000000000000001 + VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0b00000000000000000000000000000010 + VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0b00000000000000000000000000000100 + VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0b00000000000000000000000000001000 + VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0b00000000000000000000000000010000 + VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0b00000000000000000000000000100000 + VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0b00000000000000000000000001000000 + VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0b00000000000000000000000010000000 + VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0b00000000000000000000000100000000 + VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0b00000000000000000000001000000000 + VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0b00000000000000000000010000000000 + VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT = 0b00000000000000000000100000000000 + VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT = 0b00000000000000000001000000000000 + VK_QUERY_PIPELINE_STATISTIC_CLUSTER_CULLING_SHADER_INVOCATIONS_BIT_HUAWEI = 0b00000000000000000010000000000000 +func toBits*(flags: openArray[VkQueryPipelineStatisticFlagBits]): VkQueryPipelineStatisticFlags = + for flag in flags: + result = VkQueryPipelineStatisticFlags(uint(result) or uint(flag)) +func toEnums*(number: VkQueryPipelineStatisticFlags): seq[VkQueryPipelineStatisticFlagBits] = + for value in VkQueryPipelineStatisticFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkQueryPipelineStatisticFlags): bool = cint(a) == cint(b) +type + VkImageAspectFlagBits* {.size: sizeof(cint).} = enum + VK_IMAGE_ASPECT_COLOR_BIT = 0b00000000000000000000000000000001 + VK_IMAGE_ASPECT_DEPTH_BIT = 0b00000000000000000000000000000010 + VK_IMAGE_ASPECT_STENCIL_BIT = 0b00000000000000000000000000000100 + VK_IMAGE_ASPECT_METADATA_BIT = 0b00000000000000000000000000001000 + VK_IMAGE_ASPECT_PLANE_0_BIT = 0b00000000000000000000000000010000 + VK_IMAGE_ASPECT_PLANE_1_BIT = 0b00000000000000000000000000100000 + VK_IMAGE_ASPECT_PLANE_2_BIT = 0b00000000000000000000000001000000 + VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0b00000000000000000000000010000000 + VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0b00000000000000000000000100000000 + VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0b00000000000000000000001000000000 + VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0b00000000000000000000010000000000 +func toBits*(flags: openArray[VkImageAspectFlagBits]): VkImageAspectFlags = + for flag in flags: + result = VkImageAspectFlags(uint(result) or uint(flag)) +func toEnums*(number: VkImageAspectFlags): seq[VkImageAspectFlagBits] = + for value in VkImageAspectFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkImageAspectFlags): bool = cint(a) == cint(b) +type + VkSparseImageFormatFlagBits* {.size: sizeof(cint).} = enum + VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0b00000000000000000000000000000001 + VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0b00000000000000000000000000000010 + VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkSparseImageFormatFlagBits]): VkSparseImageFormatFlags = + for flag in flags: + result = VkSparseImageFormatFlags(uint(result) or uint(flag)) +func toEnums*(number: VkSparseImageFormatFlags): seq[VkSparseImageFormatFlagBits] = + for value in VkSparseImageFormatFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSparseImageFormatFlags): bool = cint(a) == cint(b) +type + VkSparseMemoryBindFlagBits* {.size: sizeof(cint).} = enum + VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkSparseMemoryBindFlagBits]): VkSparseMemoryBindFlags = + for flag in flags: + result = VkSparseMemoryBindFlags(uint(result) or uint(flag)) +func toEnums*(number: VkSparseMemoryBindFlags): seq[VkSparseMemoryBindFlagBits] = + for value in VkSparseMemoryBindFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSparseMemoryBindFlags): bool = cint(a) == cint(b) +type + VkPipelineStageFlagBits* {.size: sizeof(cint).} = enum + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0b00000000000000000000000000000001 + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0b00000000000000000000000000000010 + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0b00000000000000000000000000000100 + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0b00000000000000000000000000001000 + VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0b00000000000000000000000000010000 + VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0b00000000000000000000000000100000 + VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0b00000000000000000000000001000000 + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0b00000000000000000000000010000000 + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0b00000000000000000000000100000000 + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0b00000000000000000000001000000000 + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0b00000000000000000000010000000000 + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0b00000000000000000000100000000000 + VK_PIPELINE_STAGE_TRANSFER_BIT = 0b00000000000000000001000000000000 + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0b00000000000000000010000000000000 + VK_PIPELINE_STAGE_HOST_BIT = 0b00000000000000000100000000000000 + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0b00000000000000001000000000000000 + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0b00000000000000010000000000000000 + VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0b00000000000000100000000000000000 + VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0b00000000000001000000000000000000 + VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT = 0b00000000000010000000000000000000 + VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT = 0b00000000000100000000000000000000 + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0b00000000001000000000000000000000 + VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b00000000010000000000000000000000 + VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0b00000000100000000000000000000000 + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0b00000001000000000000000000000000 + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0b00000010000000000000000000000000 +func toBits*(flags: openArray[VkPipelineStageFlagBits]): VkPipelineStageFlags = + for flag in flags: + result = VkPipelineStageFlags(uint(result) or uint(flag)) +func toEnums*(number: VkPipelineStageFlags): seq[VkPipelineStageFlagBits] = + for value in VkPipelineStageFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPipelineStageFlags): bool = cint(a) == cint(b) +type + VkCommandPoolCreateFlagBits* {.size: sizeof(cint).} = enum + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0b00000000000000000000000000000001 + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0b00000000000000000000000000000010 + VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkCommandPoolCreateFlagBits]): VkCommandPoolCreateFlags = + for flag in flags: + result = VkCommandPoolCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkCommandPoolCreateFlags): seq[VkCommandPoolCreateFlagBits] = + for value in VkCommandPoolCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkCommandPoolCreateFlags): bool = cint(a) == cint(b) +type + VkCommandPoolResetFlagBits* {.size: sizeof(cint).} = enum + VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0b00000000000000000000000000000001 + VK_COMMAND_POOL_RESET_RESERVED_1_BIT_COREAVI = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkCommandPoolResetFlagBits]): VkCommandPoolResetFlags = + for flag in flags: + result = VkCommandPoolResetFlags(uint(result) or uint(flag)) +func toEnums*(number: VkCommandPoolResetFlags): seq[VkCommandPoolResetFlagBits] = + for value in VkCommandPoolResetFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkCommandPoolResetFlags): bool = cint(a) == cint(b) +type + VkCommandBufferResetFlagBits* {.size: sizeof(cint).} = enum + VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkCommandBufferResetFlagBits]): VkCommandBufferResetFlags = + for flag in flags: + result = VkCommandBufferResetFlags(uint(result) or uint(flag)) +func toEnums*(number: VkCommandBufferResetFlags): seq[VkCommandBufferResetFlagBits] = + for value in VkCommandBufferResetFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkCommandBufferResetFlags): bool = cint(a) == cint(b) +type + VkSampleCountFlagBits* {.size: sizeof(cint).} = enum + VK_SAMPLE_COUNT_1_BIT = 0b00000000000000000000000000000001 + VK_SAMPLE_COUNT_2_BIT = 0b00000000000000000000000000000010 + VK_SAMPLE_COUNT_4_BIT = 0b00000000000000000000000000000100 + VK_SAMPLE_COUNT_8_BIT = 0b00000000000000000000000000001000 + VK_SAMPLE_COUNT_16_BIT = 0b00000000000000000000000000010000 + VK_SAMPLE_COUNT_32_BIT = 0b00000000000000000000000000100000 + VK_SAMPLE_COUNT_64_BIT = 0b00000000000000000000000001000000 +func toBits*(flags: openArray[VkSampleCountFlagBits]): VkSampleCountFlags = + for flag in flags: + result = VkSampleCountFlags(uint(result) or uint(flag)) +func toEnums*(number: VkSampleCountFlags): seq[VkSampleCountFlagBits] = + for value in VkSampleCountFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSampleCountFlags): bool = cint(a) == cint(b) +type + VkAttachmentDescriptionFlagBits* {.size: sizeof(cint).} = enum + VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkAttachmentDescriptionFlagBits]): VkAttachmentDescriptionFlags = + for flag in flags: + result = VkAttachmentDescriptionFlags(uint(result) or uint(flag)) +func toEnums*(number: VkAttachmentDescriptionFlags): seq[VkAttachmentDescriptionFlagBits] = + for value in VkAttachmentDescriptionFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkAttachmentDescriptionFlags): bool = cint(a) == cint(b) +type + VkStencilFaceFlagBits* {.size: sizeof(cint).} = enum + VK_STENCIL_FACE_FRONT_BIT = 0b00000000000000000000000000000001 + VK_STENCIL_FACE_BACK_BIT = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkStencilFaceFlagBits]): VkStencilFaceFlags = + for flag in flags: + result = VkStencilFaceFlags(uint(result) or uint(flag)) +func toEnums*(number: VkStencilFaceFlags): seq[VkStencilFaceFlagBits] = + for value in VkStencilFaceFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkStencilFaceFlags): bool = cint(a) == cint(b) +const + VK_STENCIL_FACE_FRONT_AND_BACK* = 0x00000003 +type + VkDescriptorPoolCreateFlagBits* {.size: sizeof(cint).} = enum + VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0b00000000000000000000000000000001 + VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0b00000000000000000000000000000010 + VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkDescriptorPoolCreateFlagBits]): VkDescriptorPoolCreateFlags = + for flag in flags: + result = VkDescriptorPoolCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkDescriptorPoolCreateFlags): seq[VkDescriptorPoolCreateFlagBits] = + for value in VkDescriptorPoolCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDescriptorPoolCreateFlags): bool = cint(a) == cint(b) +type + VkDependencyFlagBits* {.size: sizeof(cint).} = enum + VK_DEPENDENCY_BY_REGION_BIT = 0b00000000000000000000000000000001 + VK_DEPENDENCY_VIEW_LOCAL_BIT = 0b00000000000000000000000000000010 + VK_DEPENDENCY_DEVICE_GROUP_BIT = 0b00000000000000000000000000000100 + VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkDependencyFlagBits]): VkDependencyFlags = + for flag in flags: + result = VkDependencyFlags(uint(result) or uint(flag)) +func toEnums*(number: VkDependencyFlags): seq[VkDependencyFlagBits] = + for value in VkDependencyFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDependencyFlags): bool = cint(a) == cint(b) +type + VkSemaphoreType* {.size: sizeof(cint).} = enum + VK_SEMAPHORE_TYPE_BINARY = 0 + VK_SEMAPHORE_TYPE_TIMELINE = 1 + VkSemaphoreWaitFlagBits* {.size: sizeof(cint).} = enum + VK_SEMAPHORE_WAIT_ANY_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkSemaphoreWaitFlagBits]): VkSemaphoreWaitFlags = + for flag in flags: + result = VkSemaphoreWaitFlags(uint(result) or uint(flag)) +func toEnums*(number: VkSemaphoreWaitFlags): seq[VkSemaphoreWaitFlagBits] = + for value in VkSemaphoreWaitFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSemaphoreWaitFlags): bool = cint(a) == cint(b) +type + VkPresentModeKHR* {.size: sizeof(cint).} = enum + VK_PRESENT_MODE_IMMEDIATE_KHR = 0 + VK_PRESENT_MODE_MAILBOX_KHR = 1 + VK_PRESENT_MODE_FIFO_KHR = 2 + VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3 + VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000 + VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001 + VkColorSpaceKHR* {.size: sizeof(cint).} = enum + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0 + VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001 + VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002 + VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104003 + VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004 + VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005 + VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006 + VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007 + VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008 + VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009 + VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010 + VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011 + VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012 + VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013 + VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014 + VK_COLOR_SPACE_DISPLAY_NATIVE_AMD = 1000213000 + VkDisplayPlaneAlphaFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0b00000000000000000000000000000001 + VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0b00000000000000000000000000000010 + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0b00000000000000000000000000000100 + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkDisplayPlaneAlphaFlagBitsKHR]): VkDisplayPlaneAlphaFlagsKHR = + for flag in flags: + result = VkDisplayPlaneAlphaFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkDisplayPlaneAlphaFlagsKHR): seq[VkDisplayPlaneAlphaFlagBitsKHR] = + for value in VkDisplayPlaneAlphaFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDisplayPlaneAlphaFlagsKHR): bool = cint(a) == cint(b) +type + VkCompositeAlphaFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0b00000000000000000000000000000001 + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0b00000000000000000000000000000010 + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0b00000000000000000000000000000100 + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkCompositeAlphaFlagBitsKHR]): VkCompositeAlphaFlagsKHR = + for flag in flags: + result = VkCompositeAlphaFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkCompositeAlphaFlagsKHR): seq[VkCompositeAlphaFlagBitsKHR] = + for value in VkCompositeAlphaFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkCompositeAlphaFlagsKHR): bool = cint(a) == cint(b) +type + VkSurfaceTransformFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0b00000000000000000000000000000001 + VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0b00000000000000000000000000000010 + VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0b00000000000000000000000000000100 + VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0b00000000000000000000000000001000 + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0b00000000000000000000000000010000 + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0b00000000000000000000000000100000 + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0b00000000000000000000000001000000 + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0b00000000000000000000000010000000 + VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0b00000000000000000000000100000000 +func toBits*(flags: openArray[VkSurfaceTransformFlagBitsKHR]): VkSurfaceTransformFlagsKHR = + for flag in flags: + result = VkSurfaceTransformFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkSurfaceTransformFlagsKHR): seq[VkSurfaceTransformFlagBitsKHR] = + for value in VkSurfaceTransformFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSurfaceTransformFlagsKHR): bool = cint(a) == cint(b) +type + VkSwapchainImageUsageFlagBitsANDROID* {.size: sizeof(cint).} = enum + VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkSwapchainImageUsageFlagBitsANDROID]): VkSwapchainImageUsageFlagsANDROID = + for flag in flags: + result = VkSwapchainImageUsageFlagsANDROID(uint(result) or uint(flag)) +func toEnums*(number: VkSwapchainImageUsageFlagsANDROID): seq[VkSwapchainImageUsageFlagBitsANDROID] = + for value in VkSwapchainImageUsageFlagBitsANDROID.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSwapchainImageUsageFlagsANDROID): bool = cint(a) == cint(b) +type + VkTimeDomainEXT* {.size: sizeof(cint).} = enum + VK_TIME_DOMAIN_DEVICE_EXT = 0 + VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = 1 + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = 2 + VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = 3 + VkDebugReportFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0b00000000000000000000000000000001 + VK_DEBUG_REPORT_WARNING_BIT_EXT = 0b00000000000000000000000000000010 + VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0b00000000000000000000000000000100 + VK_DEBUG_REPORT_ERROR_BIT_EXT = 0b00000000000000000000000000001000 + VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0b00000000000000000000000000010000 +func toBits*(flags: openArray[VkDebugReportFlagBitsEXT]): VkDebugReportFlagsEXT = + for flag in flags: + result = VkDebugReportFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkDebugReportFlagsEXT): seq[VkDebugReportFlagBitsEXT] = + for value in VkDebugReportFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDebugReportFlagsEXT): bool = cint(a) == cint(b) +type + VkDebugReportObjectTypeEXT* {.size: sizeof(cint).} = enum + VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0 + VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1 + VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT = 2 + VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT = 3 + VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT = 4 + VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT = 5 + VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT = 6 + VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT = 7 + VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT = 8 + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT = 9 + VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT = 10 + VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT = 11 + VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT = 12 + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT = 13 + VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT = 14 + VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT = 15 + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT = 16 + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT = 17 + VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT = 18 + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT = 19 + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT = 20 + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT = 21 + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT = 22 + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT = 23 + VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT = 24 + VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT = 25 + VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26 + VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27 + VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28 + VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29 + VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30 + VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33 + VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT = 1000029000 + VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT = 1000029001 + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000 + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000150000 + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000 + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000 + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT = 1000366000 + VkDeviceMemoryReportEventTypeEXT* {.size: sizeof(cint).} = enum + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT = 0 + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT = 1 + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT = 2 + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT = 3 + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT = 4 + VkRasterizationOrderAMD* {.size: sizeof(cint).} = enum + VK_RASTERIZATION_ORDER_STRICT_AMD = 0 + VK_RASTERIZATION_ORDER_RELAXED_AMD = 1 + VkExternalMemoryHandleTypeFlagBitsNV* {.size: sizeof(cint).} = enum + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0b00000000000000000000000000000001 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0b00000000000000000000000000000010 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0b00000000000000000000000000000100 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkExternalMemoryHandleTypeFlagBitsNV]): VkExternalMemoryHandleTypeFlagsNV = + for flag in flags: + result = VkExternalMemoryHandleTypeFlagsNV(uint(result) or uint(flag)) +func toEnums*(number: VkExternalMemoryHandleTypeFlagsNV): seq[VkExternalMemoryHandleTypeFlagBitsNV] = + for value in VkExternalMemoryHandleTypeFlagBitsNV.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkExternalMemoryHandleTypeFlagsNV): bool = cint(a) == cint(b) +type + VkExternalMemoryFeatureFlagBitsNV* {.size: sizeof(cint).} = enum + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0b00000000000000000000000000000001 + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0b00000000000000000000000000000010 + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkExternalMemoryFeatureFlagBitsNV]): VkExternalMemoryFeatureFlagsNV = + for flag in flags: + result = VkExternalMemoryFeatureFlagsNV(uint(result) or uint(flag)) +func toEnums*(number: VkExternalMemoryFeatureFlagsNV): seq[VkExternalMemoryFeatureFlagBitsNV] = + for value in VkExternalMemoryFeatureFlagBitsNV.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkExternalMemoryFeatureFlagsNV): bool = cint(a) == cint(b) +type + VkValidationCheckEXT* {.size: sizeof(cint).} = enum + VK_VALIDATION_CHECK_ALL_EXT = 0 + VK_VALIDATION_CHECK_SHADERS_EXT = 1 + VkValidationFeatureEnableEXT* {.size: sizeof(cint).} = enum + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0 + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1 + VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2 + VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3 + VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT = 4 + VkValidationFeatureDisableEXT* {.size: sizeof(cint).} = enum + VK_VALIDATION_FEATURE_DISABLE_ALL_EXT = 0 + VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT = 1 + VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT = 2 + VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT = 3 + VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4 + VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5 + VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6 + VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT = 7 + VkSubgroupFeatureFlagBits* {.size: sizeof(cint).} = enum + VK_SUBGROUP_FEATURE_BASIC_BIT = 0b00000000000000000000000000000001 + VK_SUBGROUP_FEATURE_VOTE_BIT = 0b00000000000000000000000000000010 + VK_SUBGROUP_FEATURE_ARITHMETIC_BIT = 0b00000000000000000000000000000100 + VK_SUBGROUP_FEATURE_BALLOT_BIT = 0b00000000000000000000000000001000 + VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 0b00000000000000000000000000010000 + VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0b00000000000000000000000000100000 + VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0b00000000000000000000000001000000 + VK_SUBGROUP_FEATURE_QUAD_BIT = 0b00000000000000000000000010000000 + VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV = 0b00000000000000000000000100000000 +func toBits*(flags: openArray[VkSubgroupFeatureFlagBits]): VkSubgroupFeatureFlags = + for flag in flags: + result = VkSubgroupFeatureFlags(uint(result) or uint(flag)) +func toEnums*(number: VkSubgroupFeatureFlags): seq[VkSubgroupFeatureFlagBits] = + for value in VkSubgroupFeatureFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSubgroupFeatureFlags): bool = cint(a) == cint(b) +type + VkIndirectCommandsLayoutUsageFlagBitsNV* {.size: sizeof(cint).} = enum + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0b00000000000000000000000000000001 + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0b00000000000000000000000000000010 + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkIndirectCommandsLayoutUsageFlagBitsNV]): VkIndirectCommandsLayoutUsageFlagsNV = + for flag in flags: + result = VkIndirectCommandsLayoutUsageFlagsNV(uint(result) or uint(flag)) +func toEnums*(number: VkIndirectCommandsLayoutUsageFlagsNV): seq[VkIndirectCommandsLayoutUsageFlagBitsNV] = + for value in VkIndirectCommandsLayoutUsageFlagBitsNV.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkIndirectCommandsLayoutUsageFlagsNV): bool = cint(a) == cint(b) +type + VkIndirectStateFlagBitsNV* {.size: sizeof(cint).} = enum + VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkIndirectStateFlagBitsNV]): VkIndirectStateFlagsNV = + for flag in flags: + result = VkIndirectStateFlagsNV(uint(result) or uint(flag)) +func toEnums*(number: VkIndirectStateFlagsNV): seq[VkIndirectStateFlagBitsNV] = + for value in VkIndirectStateFlagBitsNV.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkIndirectStateFlagsNV): bool = cint(a) == cint(b) +type + VkIndirectCommandsTokenTypeNV* {.size: sizeof(cint).} = enum + VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV = 0 + VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV = 1 + VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV = 2 + VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV = 3 + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV = 4 + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5 + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6 + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7 + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV = 1000328000 + VkPrivateDataSlotCreateFlagBits* {.size: sizeof(cint).} = enum + VK_PRIVATE_DATA_SLOT_CREATE_RESERVED_0_BIT_NV = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkPrivateDataSlotCreateFlagBits]): VkPrivateDataSlotCreateFlags = + for flag in flags: + result = VkPrivateDataSlotCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkPrivateDataSlotCreateFlags): seq[VkPrivateDataSlotCreateFlagBits] = + for value in VkPrivateDataSlotCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPrivateDataSlotCreateFlags): bool = cint(a) == cint(b) +type + VkDescriptorSetLayoutCreateFlagBits* {.size: sizeof(cint).} = enum + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0b00000000000000000000000000000001 + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0b00000000000000000000000000000010 + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT = 0b00000000000000000000000000000100 + VK_DESCRIPTOR_SET_LAYOUT_CREATE_RESERVED_3_BIT_AMD = 0b00000000000000000000000000001000 + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT = 0b00000000000000000000000000010000 + VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT = 0b00000000000000000000000000100000 +func toBits*(flags: openArray[VkDescriptorSetLayoutCreateFlagBits]): VkDescriptorSetLayoutCreateFlags = + for flag in flags: + result = VkDescriptorSetLayoutCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkDescriptorSetLayoutCreateFlags): seq[VkDescriptorSetLayoutCreateFlagBits] = + for value in VkDescriptorSetLayoutCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDescriptorSetLayoutCreateFlags): bool = cint(a) == cint(b) +type + VkExternalMemoryHandleTypeFlagBits* {.size: sizeof(cint).} = enum + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 0b00000000000000000000000000000001 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0b00000000000000000000000000000010 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0b00000000000000000000000000000100 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 0b00000000000000000000000000001000 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 0b00000000000000000000000000010000 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 0b00000000000000000000000000100000 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 0b00000000000000000000000001000000 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT = 0b00000000000000000000000010000000 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0b00000000000000000000000100000000 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT = 0b00000000000000000000001000000000 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID = 0b00000000000000000000010000000000 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA = 0b00000000000000000000100000000000 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV = 0b00000000000000000001000000000000 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCI_BUF_BIT_NV = 0b00000000000000000010000000000000 +func toBits*(flags: openArray[VkExternalMemoryHandleTypeFlagBits]): VkExternalMemoryHandleTypeFlags = + for flag in flags: + result = VkExternalMemoryHandleTypeFlags(uint(result) or uint(flag)) +func toEnums*(number: VkExternalMemoryHandleTypeFlags): seq[VkExternalMemoryHandleTypeFlagBits] = + for value in VkExternalMemoryHandleTypeFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkExternalMemoryHandleTypeFlags): bool = cint(a) == cint(b) +type + VkExternalMemoryFeatureFlagBits* {.size: sizeof(cint).} = enum + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 0b00000000000000000000000000000001 + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 0b00000000000000000000000000000010 + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkExternalMemoryFeatureFlagBits]): VkExternalMemoryFeatureFlags = + for flag in flags: + result = VkExternalMemoryFeatureFlags(uint(result) or uint(flag)) +func toEnums*(number: VkExternalMemoryFeatureFlags): seq[VkExternalMemoryFeatureFlagBits] = + for value in VkExternalMemoryFeatureFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkExternalMemoryFeatureFlags): bool = cint(a) == cint(b) +type + VkExternalSemaphoreHandleTypeFlagBits* {.size: sizeof(cint).} = enum + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 0b00000000000000000000000000000001 + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0b00000000000000000000000000000010 + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0b00000000000000000000000000000100 + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0b00000000000000000000000000001000 + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0b00000000000000000000000000010000 + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SCI_SYNC_OBJ_BIT_NV = 0b00000000000000000000000000100000 + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA = 0b00000000000000000000000010000000 +func toBits*(flags: openArray[VkExternalSemaphoreHandleTypeFlagBits]): VkExternalSemaphoreHandleTypeFlags = + for flag in flags: + result = VkExternalSemaphoreHandleTypeFlags(uint(result) or uint(flag)) +func toEnums*(number: VkExternalSemaphoreHandleTypeFlags): seq[VkExternalSemaphoreHandleTypeFlagBits] = + for value in VkExternalSemaphoreHandleTypeFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkExternalSemaphoreHandleTypeFlags): bool = cint(a) == cint(b) +type + VkExternalSemaphoreFeatureFlagBits* {.size: sizeof(cint).} = enum + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 0b00000000000000000000000000000001 + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkExternalSemaphoreFeatureFlagBits]): VkExternalSemaphoreFeatureFlags = + for flag in flags: + result = VkExternalSemaphoreFeatureFlags(uint(result) or uint(flag)) +func toEnums*(number: VkExternalSemaphoreFeatureFlags): seq[VkExternalSemaphoreFeatureFlagBits] = + for value in VkExternalSemaphoreFeatureFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkExternalSemaphoreFeatureFlags): bool = cint(a) == cint(b) +type + VkSemaphoreImportFlagBits* {.size: sizeof(cint).} = enum + VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkSemaphoreImportFlagBits]): VkSemaphoreImportFlags = + for flag in flags: + result = VkSemaphoreImportFlags(uint(result) or uint(flag)) +func toEnums*(number: VkSemaphoreImportFlags): seq[VkSemaphoreImportFlagBits] = + for value in VkSemaphoreImportFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSemaphoreImportFlags): bool = cint(a) == cint(b) +type + VkExternalFenceHandleTypeFlagBits* {.size: sizeof(cint).} = enum + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 0b00000000000000000000000000000001 + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0b00000000000000000000000000000010 + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0b00000000000000000000000000000100 + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 0b00000000000000000000000000001000 + VK_EXTERNAL_FENCE_HANDLE_TYPE_SCI_SYNC_OBJ_BIT_NV = 0b00000000000000000000000000010000 + VK_EXTERNAL_FENCE_HANDLE_TYPE_SCI_SYNC_FENCE_BIT_NV = 0b00000000000000000000000000100000 +func toBits*(flags: openArray[VkExternalFenceHandleTypeFlagBits]): VkExternalFenceHandleTypeFlags = + for flag in flags: + result = VkExternalFenceHandleTypeFlags(uint(result) or uint(flag)) +func toEnums*(number: VkExternalFenceHandleTypeFlags): seq[VkExternalFenceHandleTypeFlagBits] = + for value in VkExternalFenceHandleTypeFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkExternalFenceHandleTypeFlags): bool = cint(a) == cint(b) +type + VkExternalFenceFeatureFlagBits* {.size: sizeof(cint).} = enum + VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 0b00000000000000000000000000000001 + VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkExternalFenceFeatureFlagBits]): VkExternalFenceFeatureFlags = + for flag in flags: + result = VkExternalFenceFeatureFlags(uint(result) or uint(flag)) +func toEnums*(number: VkExternalFenceFeatureFlags): seq[VkExternalFenceFeatureFlagBits] = + for value in VkExternalFenceFeatureFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkExternalFenceFeatureFlags): bool = cint(a) == cint(b) +type + VkFenceImportFlagBits* {.size: sizeof(cint).} = enum + VK_FENCE_IMPORT_TEMPORARY_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkFenceImportFlagBits]): VkFenceImportFlags = + for flag in flags: + result = VkFenceImportFlags(uint(result) or uint(flag)) +func toEnums*(number: VkFenceImportFlags): seq[VkFenceImportFlagBits] = + for value in VkFenceImportFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkFenceImportFlags): bool = cint(a) == cint(b) +type + VkSurfaceCounterFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_SURFACE_COUNTER_VBLANK_BIT_EXT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkSurfaceCounterFlagBitsEXT]): VkSurfaceCounterFlagsEXT = + for flag in flags: + result = VkSurfaceCounterFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkSurfaceCounterFlagsEXT): seq[VkSurfaceCounterFlagBitsEXT] = + for value in VkSurfaceCounterFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSurfaceCounterFlagsEXT): bool = cint(a) == cint(b) +type + VkDisplayPowerStateEXT* {.size: sizeof(cint).} = enum + VK_DISPLAY_POWER_STATE_OFF_EXT = 0 + VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1 + VK_DISPLAY_POWER_STATE_ON_EXT = 2 + VkDeviceEventTypeEXT* {.size: sizeof(cint).} = enum + VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0 + VkDisplayEventTypeEXT* {.size: sizeof(cint).} = enum + VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0 + VkPeerMemoryFeatureFlagBits* {.size: sizeof(cint).} = enum + VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0b00000000000000000000000000000001 + VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0b00000000000000000000000000000010 + VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0b00000000000000000000000000000100 + VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkPeerMemoryFeatureFlagBits]): VkPeerMemoryFeatureFlags = + for flag in flags: + result = VkPeerMemoryFeatureFlags(uint(result) or uint(flag)) +func toEnums*(number: VkPeerMemoryFeatureFlags): seq[VkPeerMemoryFeatureFlagBits] = + for value in VkPeerMemoryFeatureFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPeerMemoryFeatureFlags): bool = cint(a) == cint(b) +type + VkMemoryAllocateFlagBits* {.size: sizeof(cint).} = enum + VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0b00000000000000000000000000000001 + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 0b00000000000000000000000000000010 + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkMemoryAllocateFlagBits]): VkMemoryAllocateFlags = + for flag in flags: + result = VkMemoryAllocateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkMemoryAllocateFlags): seq[VkMemoryAllocateFlagBits] = + for value in VkMemoryAllocateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkMemoryAllocateFlags): bool = cint(a) == cint(b) +type + VkDeviceGroupPresentModeFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0b00000000000000000000000000000001 + VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0b00000000000000000000000000000010 + VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0b00000000000000000000000000000100 + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkDeviceGroupPresentModeFlagBitsKHR]): VkDeviceGroupPresentModeFlagsKHR = + for flag in flags: + result = VkDeviceGroupPresentModeFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkDeviceGroupPresentModeFlagsKHR): seq[VkDeviceGroupPresentModeFlagBitsKHR] = + for value in VkDeviceGroupPresentModeFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDeviceGroupPresentModeFlagsKHR): bool = cint(a) == cint(b) +type + VkSwapchainCreateFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0b00000000000000000000000000000001 + VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0b00000000000000000000000000000010 + VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0b00000000000000000000000000000100 + VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT = 0b00000000000000000000000000001000 + VK_SWAPCHAIN_CREATE_RESERVED_4_BIT_EXT = 0b00000000000000000000000000010000 +func toBits*(flags: openArray[VkSwapchainCreateFlagBitsKHR]): VkSwapchainCreateFlagsKHR = + for flag in flags: + result = VkSwapchainCreateFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkSwapchainCreateFlagsKHR): seq[VkSwapchainCreateFlagBitsKHR] = + for value in VkSwapchainCreateFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSwapchainCreateFlagsKHR): bool = cint(a) == cint(b) +type + VkViewportCoordinateSwizzleNV* {.size: sizeof(cint).} = enum + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0 + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1 + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2 + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3 + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4 + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5 + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6 + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7 + VkDiscardRectangleModeEXT* {.size: sizeof(cint).} = enum + VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0 + VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1 + VkSubpassDescriptionFlagBits* {.size: sizeof(cint).} = enum + VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0b00000000000000000000000000000001 + VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0b00000000000000000000000000000010 + VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM = 0b00000000000000000000000000000100 + VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM = 0b00000000000000000000000000001000 + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT = 0b00000000000000000000000000010000 + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0b00000000000000000000000000100000 + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0b00000000000000000000000001000000 + VK_SUBPASS_DESCRIPTION_ENABLE_LEGACY_DITHERING_BIT_EXT = 0b00000000000000000000000010000000 +func toBits*(flags: openArray[VkSubpassDescriptionFlagBits]): VkSubpassDescriptionFlags = + for flag in flags: + result = VkSubpassDescriptionFlags(uint(result) or uint(flag)) +func toEnums*(number: VkSubpassDescriptionFlags): seq[VkSubpassDescriptionFlagBits] = + for value in VkSubpassDescriptionFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSubpassDescriptionFlags): bool = cint(a) == cint(b) +type + VkPointClippingBehavior* {.size: sizeof(cint).} = enum + VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0 + VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1 + VkSamplerReductionMode* {.size: sizeof(cint).} = enum + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0 + VK_SAMPLER_REDUCTION_MODE_MIN = 1 + VK_SAMPLER_REDUCTION_MODE_MAX = 2 + VkTessellationDomainOrigin* {.size: sizeof(cint).} = enum + VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0 + VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1 + VkSamplerYcbcrModelConversion* {.size: sizeof(cint).} = enum + VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0 + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1 + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2 + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3 + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4 + VkSamplerYcbcrRange* {.size: sizeof(cint).} = enum + VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0 + VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1 + VkChromaLocation* {.size: sizeof(cint).} = enum + VK_CHROMA_LOCATION_COSITED_EVEN = 0 + VK_CHROMA_LOCATION_MIDPOINT = 1 + VkBlendOverlapEXT* {.size: sizeof(cint).} = enum + VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0 + VK_BLEND_OVERLAP_DISJOINT_EXT = 1 + VK_BLEND_OVERLAP_CONJOINT_EXT = 2 + VkCoverageModulationModeNV* {.size: sizeof(cint).} = enum + VK_COVERAGE_MODULATION_MODE_NONE_NV = 0 + VK_COVERAGE_MODULATION_MODE_RGB_NV = 1 + VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2 + VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3 + VkCoverageReductionModeNV* {.size: sizeof(cint).} = enum + VK_COVERAGE_REDUCTION_MODE_MERGE_NV = 0 + VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV = 1 + VkValidationCacheHeaderVersionEXT* {.size: sizeof(cint).} = enum + VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1 + VkShaderInfoTypeAMD* {.size: sizeof(cint).} = enum + VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0 + VK_SHADER_INFO_TYPE_BINARY_AMD = 1 + VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2 + VkQueueGlobalPriorityKHR* {.size: sizeof(cint).} = enum + VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR = 128 + VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR = 256 + VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR = 512 + VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR = 1024 + VkDebugUtilsMessageSeverityFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0b00000000000000000000000000000001 + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0b00000000000000000000000000010000 + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0b00000000000000000000000100000000 + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0b00000000000000000001000000000000 +func toBits*(flags: openArray[VkDebugUtilsMessageSeverityFlagBitsEXT]): VkDebugUtilsMessageSeverityFlagsEXT = + for flag in flags: + result = VkDebugUtilsMessageSeverityFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkDebugUtilsMessageSeverityFlagsEXT): seq[VkDebugUtilsMessageSeverityFlagBitsEXT] = + for value in VkDebugUtilsMessageSeverityFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDebugUtilsMessageSeverityFlagsEXT): bool = cint(a) == cint(b) +type + VkDebugUtilsMessageTypeFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0b00000000000000000000000000000001 + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0b00000000000000000000000000000010 + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0b00000000000000000000000000000100 + VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkDebugUtilsMessageTypeFlagBitsEXT]): VkDebugUtilsMessageTypeFlagsEXT = + for flag in flags: + result = VkDebugUtilsMessageTypeFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkDebugUtilsMessageTypeFlagsEXT): seq[VkDebugUtilsMessageTypeFlagBitsEXT] = + for value in VkDebugUtilsMessageTypeFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDebugUtilsMessageTypeFlagsEXT): bool = cint(a) == cint(b) +type + VkConservativeRasterizationModeEXT* {.size: sizeof(cint).} = enum + VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0 + VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1 + VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2 + VkDescriptorBindingFlagBits* {.size: sizeof(cint).} = enum + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 0b00000000000000000000000000000001 + VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0b00000000000000000000000000000010 + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0b00000000000000000000000000000100 + VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0b00000000000000000000000000001000 + VK_DESCRIPTOR_BINDING_RESERVED_4_BIT_QCOM = 0b00000000000000000000000000010000 +func toBits*(flags: openArray[VkDescriptorBindingFlagBits]): VkDescriptorBindingFlags = + for flag in flags: + result = VkDescriptorBindingFlags(uint(result) or uint(flag)) +func toEnums*(number: VkDescriptorBindingFlags): seq[VkDescriptorBindingFlagBits] = + for value in VkDescriptorBindingFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDescriptorBindingFlags): bool = cint(a) == cint(b) +type + VkVendorId* {.size: sizeof(cint).} = enum + VK_VENDOR_ID_VIV = 65537 + VK_VENDOR_ID_VSI = 65538 + VK_VENDOR_ID_KAZAN = 65539 + VK_VENDOR_ID_CODEPLAY = 65540 + VK_VENDOR_ID_MESA = 65541 + VK_VENDOR_ID_POCL = 65542 + VkDriverId* {.size: sizeof(cint).} = enum + VK_DRIVER_ID_AMD_PROPRIETARY = 1 + VK_DRIVER_ID_AMD_OPEN_SOURCE = 2 + VK_DRIVER_ID_MESA_RADV = 3 + VK_DRIVER_ID_NVIDIA_PROPRIETARY = 4 + VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS = 5 + VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA = 6 + VK_DRIVER_ID_IMAGINATION_PROPRIETARY = 7 + VK_DRIVER_ID_QUALCOMM_PROPRIETARY = 8 + VK_DRIVER_ID_ARM_PROPRIETARY = 9 + VK_DRIVER_ID_GOOGLE_SWIFTSHADER = 10 + VK_DRIVER_ID_GGP_PROPRIETARY = 11 + VK_DRIVER_ID_BROADCOM_PROPRIETARY = 12 + VK_DRIVER_ID_MESA_LLVMPIPE = 13 + VK_DRIVER_ID_MOLTENVK = 14 + VK_DRIVER_ID_COREAVI_PROPRIETARY = 15 + VK_DRIVER_ID_JUICE_PROPRIETARY = 16 + VK_DRIVER_ID_VERISILICON_PROPRIETARY = 17 + VK_DRIVER_ID_MESA_TURNIP = 18 + VK_DRIVER_ID_MESA_V3DV = 19 + VK_DRIVER_ID_MESA_PANVK = 20 + VK_DRIVER_ID_SAMSUNG_PROPRIETARY = 21 + VK_DRIVER_ID_MESA_VENUS = 22 + VK_DRIVER_ID_MESA_DOZEN = 23 + VK_DRIVER_ID_MESA_NVK = 24 + VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA = 25 + VkConditionalRenderingFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkConditionalRenderingFlagBitsEXT]): VkConditionalRenderingFlagsEXT = + for flag in flags: + result = VkConditionalRenderingFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkConditionalRenderingFlagsEXT): seq[VkConditionalRenderingFlagBitsEXT] = + for value in VkConditionalRenderingFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkConditionalRenderingFlagsEXT): bool = cint(a) == cint(b) +type + VkResolveModeFlagBits* {.size: sizeof(cint).} = enum + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT = 0b00000000000000000000000000000001 + VK_RESOLVE_MODE_AVERAGE_BIT = 0b00000000000000000000000000000010 + VK_RESOLVE_MODE_MIN_BIT = 0b00000000000000000000000000000100 + VK_RESOLVE_MODE_MAX_BIT = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkResolveModeFlagBits]): VkResolveModeFlags = + for flag in flags: + result = VkResolveModeFlags(uint(result) or uint(flag)) +func toEnums*(number: VkResolveModeFlags): seq[VkResolveModeFlagBits] = + for value in VkResolveModeFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkResolveModeFlags): bool = cint(a) == cint(b) +const + VK_RESOLVE_MODE_NONE* = 0 +type + VkShadingRatePaletteEntryNV* {.size: sizeof(cint).} = enum + VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0 + VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1 + VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2 + VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3 + VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4 + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5 + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6 + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7 + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8 + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9 + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10 + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11 + VkCoarseSampleOrderTypeNV* {.size: sizeof(cint).} = enum + VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0 + VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1 + VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2 + VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3 + VkGeometryInstanceFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0b00000000000000000000000000000001 + VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR = 0b00000000000000000000000000000010 + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0b00000000000000000000000000000100 + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0b00000000000000000000000000001000 + VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT = 0b00000000000000000000000000010000 + VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT = 0b00000000000000000000000000100000 +func toBits*(flags: openArray[VkGeometryInstanceFlagBitsKHR]): VkGeometryInstanceFlagsKHR = + for flag in flags: + result = VkGeometryInstanceFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkGeometryInstanceFlagsKHR): seq[VkGeometryInstanceFlagBitsKHR] = + for value in VkGeometryInstanceFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkGeometryInstanceFlagsKHR): bool = cint(a) == cint(b) +type + VkGeometryFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_GEOMETRY_OPAQUE_BIT_KHR = 0b00000000000000000000000000000001 + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkGeometryFlagBitsKHR]): VkGeometryFlagsKHR = + for flag in flags: + result = VkGeometryFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkGeometryFlagsKHR): seq[VkGeometryFlagBitsKHR] = + for value in VkGeometryFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkGeometryFlagsKHR): bool = cint(a) == cint(b) +type + VkBuildAccelerationStructureFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0b00000000000000000000000000000001 + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0b00000000000000000000000000000010 + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0b00000000000000000000000000000100 + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0b00000000000000000000000000001000 + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0b00000000000000000000000000010000 + VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV = 0b00000000000000000000000000100000 + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT = 0b00000000000000000000000001000000 + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT = 0b00000000000000000000000010000000 + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT = 0b00000000000000000000000100000000 + VK_BUILD_ACCELERATION_STRUCTURE_RESERVED_BIT_9_NV = 0b00000000000000000000001000000000 + VK_BUILD_ACCELERATION_STRUCTURE_RESERVED_BIT_10_NV = 0b00000000000000000000010000000000 +func toBits*(flags: openArray[VkBuildAccelerationStructureFlagBitsKHR]): VkBuildAccelerationStructureFlagsKHR = + for flag in flags: + result = VkBuildAccelerationStructureFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkBuildAccelerationStructureFlagsKHR): seq[VkBuildAccelerationStructureFlagBitsKHR] = + for value in VkBuildAccelerationStructureFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkBuildAccelerationStructureFlagsKHR): bool = cint(a) == cint(b) +type + VkAccelerationStructureCreateFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0b00000000000000000000000000000001 + VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV = 0b00000000000000000000000000000100 + VK_ACCELERATION_STRUCTURE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkAccelerationStructureCreateFlagBitsKHR]): VkAccelerationStructureCreateFlagsKHR = + for flag in flags: + result = VkAccelerationStructureCreateFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkAccelerationStructureCreateFlagsKHR): seq[VkAccelerationStructureCreateFlagBitsKHR] = + for value in VkAccelerationStructureCreateFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkAccelerationStructureCreateFlagsKHR): bool = cint(a) == cint(b) +type + VkCopyAccelerationStructureModeKHR* {.size: sizeof(cint).} = enum + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR = 0 + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR = 1 + VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR = 2 + VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR = 3 + VkBuildAccelerationStructureModeKHR* {.size: sizeof(cint).} = enum + VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR = 0 + VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR = 1 + VkAccelerationStructureTypeKHR* {.size: sizeof(cint).} = enum + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0 + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1 + VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2 + VkGeometryTypeKHR* {.size: sizeof(cint).} = enum + VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0 + VK_GEOMETRY_TYPE_AABBS_KHR = 1 + VK_GEOMETRY_TYPE_INSTANCES_KHR = 2 + VkAccelerationStructureMemoryRequirementsTypeNV* {.size: sizeof(cint).} = enum + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0 + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1 + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2 + VkAccelerationStructureBuildTypeKHR* {.size: sizeof(cint).} = enum + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0 + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1 + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2 + VkRayTracingShaderGroupTypeKHR* {.size: sizeof(cint).} = enum + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR = 0 + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR = 1 + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR = 2 + VkAccelerationStructureCompatibilityKHR* {.size: sizeof(cint).} = enum + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0 + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR = 1 + VkShaderGroupShaderKHR* {.size: sizeof(cint).} = enum + VK_SHADER_GROUP_SHADER_GENERAL_KHR = 0 + VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR = 1 + VK_SHADER_GROUP_SHADER_ANY_HIT_KHR = 2 + VK_SHADER_GROUP_SHADER_INTERSECTION_KHR = 3 + VkMemoryOverallocationBehaviorAMD* {.size: sizeof(cint).} = enum + VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0 + VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1 + VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2 + VkFramebufferCreateFlagBits* {.size: sizeof(cint).} = enum + VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkFramebufferCreateFlagBits]): VkFramebufferCreateFlags = + for flag in flags: + result = VkFramebufferCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkFramebufferCreateFlags): seq[VkFramebufferCreateFlagBits] = + for value in VkFramebufferCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkFramebufferCreateFlags): bool = cint(a) == cint(b) +type + VkScopeNV* {.size: sizeof(cint).} = enum + VK_SCOPE_DEVICE_NV = 1 + VK_SCOPE_WORKGROUP_NV = 2 + VK_SCOPE_SUBGROUP_NV = 3 + VK_SCOPE_QUEUE_FAMILY_NV = 5 + VkComponentTypeNV* {.size: sizeof(cint).} = enum + VK_COMPONENT_TYPE_FLOAT16_NV = 0 + VK_COMPONENT_TYPE_FLOAT32_NV = 1 + VK_COMPONENT_TYPE_FLOAT64_NV = 2 + VK_COMPONENT_TYPE_SINT8_NV = 3 + VK_COMPONENT_TYPE_SINT16_NV = 4 + VK_COMPONENT_TYPE_SINT32_NV = 5 + VK_COMPONENT_TYPE_SINT64_NV = 6 + VK_COMPONENT_TYPE_UINT8_NV = 7 + VK_COMPONENT_TYPE_UINT16_NV = 8 + VK_COMPONENT_TYPE_UINT32_NV = 9 + VK_COMPONENT_TYPE_UINT64_NV = 10 + VkDeviceDiagnosticsConfigFlagBitsNV* {.size: sizeof(cint).} = enum + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV = 0b00000000000000000000000000000001 + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV = 0b00000000000000000000000000000010 + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV = 0b00000000000000000000000000000100 + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkDeviceDiagnosticsConfigFlagBitsNV]): VkDeviceDiagnosticsConfigFlagsNV = + for flag in flags: + result = VkDeviceDiagnosticsConfigFlagsNV(uint(result) or uint(flag)) +func toEnums*(number: VkDeviceDiagnosticsConfigFlagsNV): seq[VkDeviceDiagnosticsConfigFlagBitsNV] = + for value in VkDeviceDiagnosticsConfigFlagBitsNV.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDeviceDiagnosticsConfigFlagsNV): bool = cint(a) == cint(b) +type + VkPipelineCreationFeedbackFlagBits* {.size: sizeof(cint).} = enum + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT = 0b00000000000000000000000000000001 + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT = 0b00000000000000000000000000000010 + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkPipelineCreationFeedbackFlagBits]): VkPipelineCreationFeedbackFlags = + for flag in flags: + result = VkPipelineCreationFeedbackFlags(uint(result) or uint(flag)) +func toEnums*(number: VkPipelineCreationFeedbackFlags): seq[VkPipelineCreationFeedbackFlagBits] = + for value in VkPipelineCreationFeedbackFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPipelineCreationFeedbackFlags): bool = cint(a) == cint(b) +type + VkFullScreenExclusiveEXT* {.size: sizeof(cint).} = enum + VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT = 0 + VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT = 1 + VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT = 2 + VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT = 3 + VkPerformanceCounterScopeKHR* {.size: sizeof(cint).} = enum + VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR = 0 + VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR = 1 + VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR = 2 + VkMemoryDecompressionMethodFlagBitsNV* {.size: 8.} = enum + VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV = 0b0000000000000000000000000000000000000000000000000000000000000001 +func toBits*(flags: openArray[VkMemoryDecompressionMethodFlagBitsNV]): VkMemoryDecompressionMethodFlagsNV = + for flag in flags: + result = VkMemoryDecompressionMethodFlagsNV(uint64(result) or uint64(flag)) +func toEnums*(number: VkMemoryDecompressionMethodFlagsNV): seq[VkMemoryDecompressionMethodFlagBitsNV] = + for value in VkMemoryDecompressionMethodFlagBitsNV.items: + if (cast[uint64](value) and uint64(number)) > 0: + result.add value +proc `==`*(a, b: VkMemoryDecompressionMethodFlagsNV): bool = uint64(a) == uint64(b) +type + VkPerformanceCounterUnitKHR* {.size: sizeof(cint).} = enum + VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR = 0 + VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR = 1 + VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR = 2 + VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR = 3 + VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR = 4 + VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR = 5 + VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR = 6 + VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR = 7 + VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR = 8 + VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR = 9 + VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR = 10 + VkPerformanceCounterStorageKHR* {.size: sizeof(cint).} = enum + VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR = 0 + VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR = 1 + VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR = 2 + VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR = 3 + VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR = 4 + VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR = 5 + VkPerformanceCounterDescriptionFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR = 0b00000000000000000000000000000001 + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkPerformanceCounterDescriptionFlagBitsKHR]): VkPerformanceCounterDescriptionFlagsKHR = + for flag in flags: + result = VkPerformanceCounterDescriptionFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkPerformanceCounterDescriptionFlagsKHR): seq[VkPerformanceCounterDescriptionFlagBitsKHR] = + for value in VkPerformanceCounterDescriptionFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPerformanceCounterDescriptionFlagsKHR): bool = cint(a) == cint(b) +type + VkPerformanceConfigurationTypeINTEL* {.size: sizeof(cint).} = enum + VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL = 0 + VkQueryPoolSamplingModeINTEL* {.size: sizeof(cint).} = enum + VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL = 0 + VkPerformanceOverrideTypeINTEL* {.size: sizeof(cint).} = enum + VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL = 0 + VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL = 1 + VkPerformanceParameterTypeINTEL* {.size: sizeof(cint).} = enum + VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL = 0 + VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL = 1 + VkPerformanceValueTypeINTEL* {.size: sizeof(cint).} = enum + VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL = 0 + VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL = 1 + VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL = 2 + VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL = 3 + VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL = 4 + VkShaderFloatControlsIndependence* {.size: sizeof(cint).} = enum + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY = 0 + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL = 1 + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE = 2 + VkPipelineExecutableStatisticFormatKHR* {.size: sizeof(cint).} = enum + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR = 0 + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR = 1 + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR = 2 + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR = 3 + VkLineRasterizationModeEXT* {.size: sizeof(cint).} = enum + VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT = 0 + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT = 1 + VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT = 2 + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT = 3 + VkFaultLevel* {.size: sizeof(cint).} = enum + VK_FAULT_LEVEL_UNASSIGNED = 0 + VK_FAULT_LEVEL_CRITICAL = 1 + VK_FAULT_LEVEL_RECOVERABLE = 2 + VK_FAULT_LEVEL_WARNING = 3 + VkFaultType* {.size: sizeof(cint).} = enum + VK_FAULT_TYPE_INVALID = 0 + VK_FAULT_TYPE_UNASSIGNED = 1 + VK_FAULT_TYPE_IMPLEMENTATION = 2 + VK_FAULT_TYPE_SYSTEM = 3 + VK_FAULT_TYPE_PHYSICAL_DEVICE = 4 + VK_FAULT_TYPE_COMMAND_BUFFER_FULL = 5 + VK_FAULT_TYPE_INVALID_API_USAGE = 6 + VkFaultQueryBehavior* {.size: sizeof(cint).} = enum + VK_FAULT_QUERY_BEHAVIOR_GET_AND_CLEAR_ALL_FAULTS = 0 + VkToolPurposeFlagBits* {.size: sizeof(cint).} = enum + VK_TOOL_PURPOSE_VALIDATION_BIT = 0b00000000000000000000000000000001 + VK_TOOL_PURPOSE_PROFILING_BIT = 0b00000000000000000000000000000010 + VK_TOOL_PURPOSE_TRACING_BIT = 0b00000000000000000000000000000100 + VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT = 0b00000000000000000000000000001000 + VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT = 0b00000000000000000000000000010000 + VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT = 0b00000000000000000000000000100000 + VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT = 0b00000000000000000000000001000000 +func toBits*(flags: openArray[VkToolPurposeFlagBits]): VkToolPurposeFlags = + for flag in flags: + result = VkToolPurposeFlags(uint(result) or uint(flag)) +func toEnums*(number: VkToolPurposeFlags): seq[VkToolPurposeFlagBits] = + for value in VkToolPurposeFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkToolPurposeFlags): bool = cint(a) == cint(b) +type + VkPipelineMatchControl* {.size: sizeof(cint).} = enum + VK_PIPELINE_MATCH_CONTROL_APPLICATION_UUID_EXACT_MATCH = 0 + VkFragmentShadingRateCombinerOpKHR* {.size: sizeof(cint).} = enum + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR = 0 + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR = 1 + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR = 2 + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR = 3 + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR = 4 + VkFragmentShadingRateNV* {.size: sizeof(cint).} = enum + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV = 0 + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV = 1 + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV = 4 + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV = 5 + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV = 6 + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV = 9 + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV = 10 + VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV = 11 + VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV = 12 + VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV = 13 + VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV = 14 + VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV = 15 + VkFragmentShadingRateTypeNV* {.size: sizeof(cint).} = enum + VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV = 0 + VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV = 1 + VkSubpassMergeStatusEXT* {.size: sizeof(cint).} = enum + VK_SUBPASS_MERGE_STATUS_MERGED_EXT = 0 + VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT = 1 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SIDE_EFFECTS_EXT = 2 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SAMPLES_MISMATCH_EXT = 3 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_VIEWS_MISMATCH_EXT = 4 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_ALIASING_EXT = 5 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPENDENCIES_EXT = 6 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INCOMPATIBLE_INPUT_ATTACHMENT_EXT = 7 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_TOO_MANY_ATTACHMENTS_EXT = 8 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INSUFFICIENT_STORAGE_EXT = 9 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPTH_STENCIL_COUNT_EXT = 10 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_RESOLVE_ATTACHMENT_REUSE_EXT = 11 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SINGLE_SUBPASS_EXT = 12 + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_UNSPECIFIED_EXT = 13 + VkAccessFlagBits2* {.size: 8.} = enum + VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000000001 + VK_ACCESS_2_INDEX_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000000010 + VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000000100 + VK_ACCESS_2_UNIFORM_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000001000 + VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000010000 + VK_ACCESS_2_SHADER_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000100000 + VK_ACCESS_2_SHADER_WRITE_BIT = 0b0000000000000000000000000000000000000000000000000000000001000000 + VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000010000000 + VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT = 0b0000000000000000000000000000000000000000000000000000000100000000 + VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0b0000000000000000000000000000000000000000000000000000001000000000 + VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0b0000000000000000000000000000000000000000000000000000010000000000 + VK_ACCESS_2_TRANSFER_READ_BIT = 0b0000000000000000000000000000000000000000000000000000100000000000 + VK_ACCESS_2_TRANSFER_WRITE_BIT = 0b0000000000000000000000000000000000000000000000000001000000000000 + VK_ACCESS_2_HOST_READ_BIT = 0b0000000000000000000000000000000000000000000000000010000000000000 + VK_ACCESS_2_HOST_WRITE_BIT = 0b0000000000000000000000000000000000000000000000000100000000000000 + VK_ACCESS_2_MEMORY_READ_BIT = 0b0000000000000000000000000000000000000000000000001000000000000000 + VK_ACCESS_2_MEMORY_WRITE_BIT = 0b0000000000000000000000000000000000000000000000010000000000000000 + VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0b0000000000000000000000000000000000000000000000100000000000000000 + VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0b0000000000000000000000000000000000000000000001000000000000000000 + VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0b0000000000000000000000000000000000000000000010000000000000000000 + VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0b0000000000000000000000000000000000000000000100000000000000000000 + VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0b0000000000000000000000000000000000000000001000000000000000000000 + VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0b0000000000000000000000000000000000000000010000000000000000000000 + VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0b0000000000000000000000000000000000000000100000000000000000000000 + VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0b0000000000000000000000000000000000000001000000000000000000000000 + VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0b0000000000000000000000000000000000000010000000000000000000000000 + VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0b0000000000000000000000000000000000000100000000000000000000000000 + VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0b0000000000000000000000000000000000001000000000000000000000000000 + VK_ACCESS_2_SHADER_SAMPLED_READ_BIT = 0b0000000000000000000000000000000100000000000000000000000000000000 + VK_ACCESS_2_SHADER_STORAGE_READ_BIT = 0b0000000000000000000000000000001000000000000000000000000000000000 + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT = 0b0000000000000000000000000000010000000000000000000000000000000000 + VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0b0000000000000000000000000000100000000000000000000000000000000000 + VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0b0000000000000000000000000001000000000000000000000000000000000000 + VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0b0000000000000000000000000010000000000000000000000000000000000000 + VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0b0000000000000000000000000100000000000000000000000000000000000000 + VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI = 0b0000000000000000000000001000000000000000000000000000000000000000 + VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR = 0b0000000000000000000000010000000000000000000000000000000000000000 + VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT = 0b0000000000000000000000100000000000000000000000000000000000000000 + VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV = 0b0000000000000000000001000000000000000000000000000000000000000000 + VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV = 0b0000000000000000000010000000000000000000000000000000000000000000 + VK_ACCESS_2_MICROMAP_READ_BIT_EXT = 0b0000000000000000000100000000000000000000000000000000000000000000 + VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT = 0b0000000000000000001000000000000000000000000000000000000000000000 + VK_ACCESS_2_RESERVED_46_BIT_EXT = 0b0000000000000000010000000000000000000000000000000000000000000000 +func toBits*(flags: openArray[VkAccessFlagBits2]): VkAccessFlags2 = + for flag in flags: + result = VkAccessFlags2(uint64(result) or uint64(flag)) +func toEnums*(number: VkAccessFlags2): seq[VkAccessFlagBits2] = + for value in VkAccessFlagBits2.items: + if (cast[uint64](value) and uint64(number)) > 0: + result.add value +proc `==`*(a, b: VkAccessFlags2): bool = uint64(a) == uint64(b) +const + VK_ACCESS_2_NONE* = 0 +type + VkPipelineStageFlagBits2* {.size: 8.} = enum + VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT = 0b0000000000000000000000000000000000000000000000000000000000000001 + VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT = 0b0000000000000000000000000000000000000000000000000000000000000010 + VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT = 0b0000000000000000000000000000000000000000000000000000000000000100 + VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000000000001000 + VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000000000010000 + VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000000000100000 + VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000000001000000 + VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000000010000000 + VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT = 0b0000000000000000000000000000000000000000000000000000000100000000 + VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT = 0b0000000000000000000000000000000000000000000000000000001000000000 + VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT = 0b0000000000000000000000000000000000000000000000000000010000000000 + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000100000000000 + VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT = 0b0000000000000000000000000000000000000000000000000001000000000000 + VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT = 0b0000000000000000000000000000000000000000000000000010000000000000 + VK_PIPELINE_STAGE_2_HOST_BIT = 0b0000000000000000000000000000000000000000000000000100000000000000 + VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT = 0b0000000000000000000000000000000000000000000000001000000000000000 + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT = 0b0000000000000000000000000000000000000000000000010000000000000000 + VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0b0000000000000000000000000000000000000000000000100000000000000000 + VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0b0000000000000000000000000000000000000000000001000000000000000000 + VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT = 0b0000000000000000000000000000000000000000000010000000000000000000 + VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT = 0b0000000000000000000000000000000000000000000100000000000000000000 + VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0b0000000000000000000000000000000000000000001000000000000000000000 + VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b0000000000000000000000000000000000000000010000000000000000000000 + VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0b0000000000000000000000000000000000000000100000000000000000000000 + VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0b0000000000000000000000000000000000000001000000000000000000000000 + VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0b0000000000000000000000000000000000000010000000000000000000000000 + VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR = 0b0000000000000000000000000000000000000100000000000000000000000000 + VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR = 0b0000000000000000000000000000000000001000000000000000000000000000 + VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR = 0b0000000000000000000000000000000000010000000000000000000000000000 + VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV = 0b0000000000000000000000000000000000100000000000000000000000000000 + VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT = 0b0000000000000000000000000000000001000000000000000000000000000000 + VK_PIPELINE_STAGE_2_COPY_BIT = 0b0000000000000000000000000000000100000000000000000000000000000000 + VK_PIPELINE_STAGE_2_RESOLVE_BIT = 0b0000000000000000000000000000001000000000000000000000000000000000 + VK_PIPELINE_STAGE_2_BLIT_BIT = 0b0000000000000000000000000000010000000000000000000000000000000000 + VK_PIPELINE_STAGE_2_CLEAR_BIT = 0b0000000000000000000000000000100000000000000000000000000000000000 + VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT = 0b0000000000000000000000000001000000000000000000000000000000000000 + VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT = 0b0000000000000000000000000010000000000000000000000000000000000000 + VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT = 0b0000000000000000000000000100000000000000000000000000000000000000 + VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0b0000000000000000000000001000000000000000000000000000000000000000 + VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0b0000000000000000000000010000000000000000000000000000000000000000 + VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI = 0b0000000000000000000000100000000000000000000000000000000000000000 +func toBits*(flags: openArray[VkPipelineStageFlagBits2]): VkPipelineStageFlags2 = + for flag in flags: + result = VkPipelineStageFlags2(uint64(result) or uint64(flag)) +func toEnums*(number: VkPipelineStageFlags2): seq[VkPipelineStageFlagBits2] = + for value in VkPipelineStageFlagBits2.items: + if (cast[uint64](value) and uint64(number)) > 0: + result.add value +proc `==`*(a, b: VkPipelineStageFlags2): bool = uint64(a) == uint64(b) +const + VK_PIPELINE_STAGE_2_NONE* = 0 +type + VkSubmitFlagBits* {.size: sizeof(cint).} = enum + VK_SUBMIT_PROTECTED_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkSubmitFlagBits]): VkSubmitFlags = + for flag in flags: + result = VkSubmitFlags(uint(result) or uint(flag)) +func toEnums*(number: VkSubmitFlags): seq[VkSubmitFlagBits] = + for value in VkSubmitFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkSubmitFlags): bool = cint(a) == cint(b) +type + VkEventCreateFlagBits* {.size: sizeof(cint).} = enum + VK_EVENT_CREATE_DEVICE_ONLY_BIT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkEventCreateFlagBits]): VkEventCreateFlags = + for flag in flags: + result = VkEventCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkEventCreateFlags): seq[VkEventCreateFlagBits] = + for value in VkEventCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkEventCreateFlags): bool = cint(a) == cint(b) +type + VkPipelineLayoutCreateFlagBits* {.size: sizeof(cint).} = enum + VK_PIPELINE_LAYOUT_CREATE_RESERVED_0_BIT_AMD = 0b00000000000000000000000000000001 + VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkPipelineLayoutCreateFlagBits]): VkPipelineLayoutCreateFlags = + for flag in flags: + result = VkPipelineLayoutCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkPipelineLayoutCreateFlags): seq[VkPipelineLayoutCreateFlagBits] = + for value in VkPipelineLayoutCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPipelineLayoutCreateFlags): bool = cint(a) == cint(b) +type + VkSciSyncClientTypeNV* {.size: sizeof(cint).} = enum + VK_SCI_SYNC_CLIENT_TYPE_SIGNALER_NV = 0 + VK_SCI_SYNC_CLIENT_TYPE_WAITER_NV = 1 + VK_SCI_SYNC_CLIENT_TYPE_SIGNALER_WAITER_NV = 2 + VkSciSyncPrimitiveTypeNV* {.size: sizeof(cint).} = enum + VK_SCI_SYNC_PRIMITIVE_TYPE_FENCE_NV = 0 + VK_SCI_SYNC_PRIMITIVE_TYPE_SEMAPHORE_NV = 1 + VkProvokingVertexModeEXT* {.size: sizeof(cint).} = enum + VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT = 0 + VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT = 1 + VkPipelineCacheValidationVersion* {.size: sizeof(cint).} = enum + VK_PIPELINE_CACHE_VALIDATION_VERSION_SAFETY_CRITICAL_ONE = 1 + VkAccelerationStructureMotionInstanceTypeNV* {.size: sizeof(cint).} = enum + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV = 0 + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV = 1 + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV = 2 + VkPipelineColorBlendStateCreateFlagBits* {.size: sizeof(cint).} = enum + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkPipelineColorBlendStateCreateFlagBits]): VkPipelineColorBlendStateCreateFlags = + for flag in flags: + result = VkPipelineColorBlendStateCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkPipelineColorBlendStateCreateFlags): seq[VkPipelineColorBlendStateCreateFlagBits] = + for value in VkPipelineColorBlendStateCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPipelineColorBlendStateCreateFlags): bool = cint(a) == cint(b) +type + VkPipelineDepthStencilStateCreateFlagBits* {.size: sizeof(cint).} = enum + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0b00000000000000000000000000000001 + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkPipelineDepthStencilStateCreateFlagBits]): VkPipelineDepthStencilStateCreateFlags = + for flag in flags: + result = VkPipelineDepthStencilStateCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkPipelineDepthStencilStateCreateFlags): seq[VkPipelineDepthStencilStateCreateFlagBits] = + for value in VkPipelineDepthStencilStateCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPipelineDepthStencilStateCreateFlags): bool = cint(a) == cint(b) +type + VkGraphicsPipelineLibraryFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT = 0b00000000000000000000000000000001 + VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT = 0b00000000000000000000000000000010 + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT = 0b00000000000000000000000000000100 + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkGraphicsPipelineLibraryFlagBitsEXT]): VkGraphicsPipelineLibraryFlagsEXT = + for flag in flags: + result = VkGraphicsPipelineLibraryFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkGraphicsPipelineLibraryFlagsEXT): seq[VkGraphicsPipelineLibraryFlagBitsEXT] = + for value in VkGraphicsPipelineLibraryFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkGraphicsPipelineLibraryFlagsEXT): bool = cint(a) == cint(b) +type + VkDeviceAddressBindingFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_DEVICE_ADDRESS_BINDING_INTERNAL_OBJECT_BIT_EXT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkDeviceAddressBindingFlagBitsEXT]): VkDeviceAddressBindingFlagsEXT = + for flag in flags: + result = VkDeviceAddressBindingFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkDeviceAddressBindingFlagsEXT): seq[VkDeviceAddressBindingFlagBitsEXT] = + for value in VkDeviceAddressBindingFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkDeviceAddressBindingFlagsEXT): bool = cint(a) == cint(b) +type + VkDeviceAddressBindingTypeEXT* {.size: sizeof(cint).} = enum + VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT = 0 + VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT = 1 + VkPresentScalingFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT = 0b00000000000000000000000000000001 + VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT = 0b00000000000000000000000000000010 + VK_PRESENT_SCALING_STRETCH_BIT_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkPresentScalingFlagBitsEXT]): VkPresentScalingFlagsEXT = + for flag in flags: + result = VkPresentScalingFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkPresentScalingFlagsEXT): seq[VkPresentScalingFlagBitsEXT] = + for value in VkPresentScalingFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPresentScalingFlagsEXT): bool = cint(a) == cint(b) +type + VkPresentGravityFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_PRESENT_GRAVITY_MIN_BIT_EXT = 0b00000000000000000000000000000001 + VK_PRESENT_GRAVITY_MAX_BIT_EXT = 0b00000000000000000000000000000010 + VK_PRESENT_GRAVITY_CENTERED_BIT_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkPresentGravityFlagBitsEXT]): VkPresentGravityFlagsEXT = + for flag in flags: + result = VkPresentGravityFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkPresentGravityFlagsEXT): seq[VkPresentGravityFlagBitsEXT] = + for value in VkPresentGravityFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkPresentGravityFlagsEXT): bool = cint(a) == cint(b) +type + VkVideoCodecOperationFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR = 0b00000000000000000000000000000010 + VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT = 0b00000000000000010000000000000000 + VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT = 0b00000000000000100000000000000000 +func toBits*(flags: openArray[VkVideoCodecOperationFlagBitsKHR]): VkVideoCodecOperationFlagsKHR = + for flag in flags: + result = VkVideoCodecOperationFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoCodecOperationFlagsKHR): seq[VkVideoCodecOperationFlagBitsKHR] = + for value in VkVideoCodecOperationFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoCodecOperationFlagsKHR): bool = cint(a) == cint(b) +const + VK_VIDEO_CODEC_OPERATION_NONE_KHR* = 0 +type + VkVideoChromaSubsamplingFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR = 0b00000000000000000000000000000010 + VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR = 0b00000000000000000000000000000100 + VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkVideoChromaSubsamplingFlagBitsKHR]): VkVideoChromaSubsamplingFlagsKHR = + for flag in flags: + result = VkVideoChromaSubsamplingFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoChromaSubsamplingFlagsKHR): seq[VkVideoChromaSubsamplingFlagBitsKHR] = + for value in VkVideoChromaSubsamplingFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoChromaSubsamplingFlagsKHR): bool = cint(a) == cint(b) +const + VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR* = 0 +type + VkVideoComponentBitDepthFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR = 0b00000000000000000000000000000100 + VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR = 0b00000000000000000000000000010000 +func toBits*(flags: openArray[VkVideoComponentBitDepthFlagBitsKHR]): VkVideoComponentBitDepthFlagsKHR = + for flag in flags: + result = VkVideoComponentBitDepthFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoComponentBitDepthFlagsKHR): seq[VkVideoComponentBitDepthFlagBitsKHR] = + for value in VkVideoComponentBitDepthFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoComponentBitDepthFlagsKHR): bool = cint(a) == cint(b) +const + VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR* = 0 +type + VkVideoCapabilityFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkVideoCapabilityFlagBitsKHR]): VkVideoCapabilityFlagsKHR = + for flag in flags: + result = VkVideoCapabilityFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoCapabilityFlagsKHR): seq[VkVideoCapabilityFlagBitsKHR] = + for value in VkVideoCapabilityFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoCapabilityFlagsKHR): bool = cint(a) == cint(b) +type + VkVideoSessionCreateFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkVideoSessionCreateFlagBitsKHR]): VkVideoSessionCreateFlagsKHR = + for flag in flags: + result = VkVideoSessionCreateFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoSessionCreateFlagsKHR): seq[VkVideoSessionCreateFlagBitsKHR] = + for value in VkVideoSessionCreateFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoSessionCreateFlagsKHR): bool = cint(a) == cint(b) +type + VkVideoDecodeH264PictureLayoutFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_KHR = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkVideoDecodeH264PictureLayoutFlagBitsKHR]): VkVideoDecodeH264PictureLayoutFlagsKHR = + for flag in flags: + result = VkVideoDecodeH264PictureLayoutFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoDecodeH264PictureLayoutFlagsKHR): seq[VkVideoDecodeH264PictureLayoutFlagBitsKHR] = + for value in VkVideoDecodeH264PictureLayoutFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoDecodeH264PictureLayoutFlagsKHR): bool = cint(a) == cint(b) +const + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR* = 0 +type + VkVideoCodingControlFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR = 0b00000000000000000000000000000010 + VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_LAYER_BIT_KHR = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkVideoCodingControlFlagBitsKHR]): VkVideoCodingControlFlagsKHR = + for flag in flags: + result = VkVideoCodingControlFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoCodingControlFlagsKHR): seq[VkVideoCodingControlFlagBitsKHR] = + for value in VkVideoCodingControlFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoCodingControlFlagsKHR): bool = cint(a) == cint(b) +type + VkQueryResultStatusKHR* {.size: sizeof(cint).} = enum + VK_QUERY_RESULT_STATUS_ERROR_KHR = -1 + VK_QUERY_RESULT_STATUS_NOT_READY_KHR = 0 + VK_QUERY_RESULT_STATUS_COMPLETE_KHR = 1 + VkVideoDecodeUsageFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_DECODE_USAGE_TRANSCODING_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_DECODE_USAGE_OFFLINE_BIT_KHR = 0b00000000000000000000000000000010 + VK_VIDEO_DECODE_USAGE_STREAMING_BIT_KHR = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkVideoDecodeUsageFlagBitsKHR]): VkVideoDecodeUsageFlagsKHR = + for flag in flags: + result = VkVideoDecodeUsageFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoDecodeUsageFlagsKHR): seq[VkVideoDecodeUsageFlagBitsKHR] = + for value in VkVideoDecodeUsageFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoDecodeUsageFlagsKHR): bool = cint(a) == cint(b) +const + VK_VIDEO_DECODE_USAGE_DEFAULT_KHR* = 0 +type + VkVideoDecodeCapabilityFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR = 0b00000000000000000000000000000010 +func toBits*(flags: openArray[VkVideoDecodeCapabilityFlagBitsKHR]): VkVideoDecodeCapabilityFlagsKHR = + for flag in flags: + result = VkVideoDecodeCapabilityFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoDecodeCapabilityFlagsKHR): seq[VkVideoDecodeCapabilityFlagBitsKHR] = + for value in VkVideoDecodeCapabilityFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoDecodeCapabilityFlagsKHR): bool = cint(a) == cint(b) +type + VkVideoEncodeUsageFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_USAGE_STREAMING_BIT_KHR = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_USAGE_RECORDING_BIT_KHR = 0b00000000000000000000000000000100 + VK_VIDEO_ENCODE_USAGE_CONFERENCING_BIT_KHR = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkVideoEncodeUsageFlagBitsKHR]): VkVideoEncodeUsageFlagsKHR = + for flag in flags: + result = VkVideoEncodeUsageFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeUsageFlagsKHR): seq[VkVideoEncodeUsageFlagBitsKHR] = + for value in VkVideoEncodeUsageFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeUsageFlagsKHR): bool = cint(a) == cint(b) +const + VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR* = 0 +type + VkVideoEncodeContentFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_CONTENT_CAMERA_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_CONTENT_DESKTOP_BIT_KHR = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_CONTENT_RENDERED_BIT_KHR = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkVideoEncodeContentFlagBitsKHR]): VkVideoEncodeContentFlagsKHR = + for flag in flags: + result = VkVideoEncodeContentFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeContentFlagsKHR): seq[VkVideoEncodeContentFlagBitsKHR] = + for value in VkVideoEncodeContentFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeContentFlagsKHR): bool = cint(a) == cint(b) +const + VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR* = 0 +type + VkVideoEncodeTuningModeKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR = 0 + VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR = 1 + VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR = 2 + VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR = 3 + VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR = 4 + VkVideoEncodeCapabilityFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkVideoEncodeCapabilityFlagBitsKHR]): VkVideoEncodeCapabilityFlagsKHR = + for flag in flags: + result = VkVideoEncodeCapabilityFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeCapabilityFlagsKHR): seq[VkVideoEncodeCapabilityFlagBitsKHR] = + for value in VkVideoEncodeCapabilityFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeCapabilityFlagsKHR): bool = cint(a) == cint(b) +type + VkVideoEncodeRateControlModeFlagBitsKHR* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkVideoEncodeRateControlModeFlagBitsKHR]): VkVideoEncodeRateControlModeFlagsKHR = + for flag in flags: + result = VkVideoEncodeRateControlModeFlagsKHR(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeRateControlModeFlagsKHR): seq[VkVideoEncodeRateControlModeFlagBitsKHR] = + for value in VkVideoEncodeRateControlModeFlagBitsKHR.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeRateControlModeFlagsKHR): bool = cint(a) == cint(b) +type + VkVideoEncodeH264CapabilityFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_ENABLED_BIT_EXT = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_DISABLED_BIT_EXT = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_H264_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT = 0b00000000000000000000000000000100 + VK_VIDEO_ENCODE_H264_CAPABILITY_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_BIT_EXT = 0b00000000000000000000000000001000 + VK_VIDEO_ENCODE_H264_CAPABILITY_SCALING_LISTS_BIT_EXT = 0b00000000000000000000000000010000 + VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_EXT = 0b00000000000000000000000000100000 + VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT = 0b00000000000000000000000001000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT = 0b00000000000000000000000010000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_PIC_INIT_QP_MINUS26_BIT_EXT = 0b00000000000000000000000100000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_BIT_EXT = 0b00000000000000000000001000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_EXPLICIT_BIT_EXT = 0b00000000000000000000010000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_IMPLICIT_BIT_EXT = 0b00000000000000000000100000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT = 0b00000000000000000001000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT = 0b00000000000000000010000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT = 0b00000000000000000100000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT = 0b00000000000000001000000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT = 0b00000000000000010000000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT = 0b00000000000000100000000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT = 0b00000000000001000000000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_DISABLE_DIRECT_SPATIAL_MV_PRED_BIT_EXT = 0b00000000000010000000000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT = 0b00000000000100000000000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_SLICE_MB_COUNT_BIT_EXT = 0b00000000001000000000000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_EXT = 0b00000000010000000000000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT = 0b00000000100000000000000000000000 + VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0b00000001000000000000000000000000 +func toBits*(flags: openArray[VkVideoEncodeH264CapabilityFlagBitsEXT]): VkVideoEncodeH264CapabilityFlagsEXT = + for flag in flags: + result = VkVideoEncodeH264CapabilityFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeH264CapabilityFlagsEXT): seq[VkVideoEncodeH264CapabilityFlagBitsEXT] = + for value in VkVideoEncodeH264CapabilityFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeH264CapabilityFlagsEXT): bool = cint(a) == cint(b) +type + VkVideoEncodeH264InputModeFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkVideoEncodeH264InputModeFlagBitsEXT]): VkVideoEncodeH264InputModeFlagsEXT = + for flag in flags: + result = VkVideoEncodeH264InputModeFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeH264InputModeFlagsEXT): seq[VkVideoEncodeH264InputModeFlagBitsEXT] = + for value in VkVideoEncodeH264InputModeFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeH264InputModeFlagsEXT): bool = cint(a) == cint(b) +type + VkVideoEncodeH264OutputModeFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkVideoEncodeH264OutputModeFlagBitsEXT]): VkVideoEncodeH264OutputModeFlagsEXT = + for flag in flags: + result = VkVideoEncodeH264OutputModeFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeH264OutputModeFlagsEXT): seq[VkVideoEncodeH264OutputModeFlagBitsEXT] = + for value in VkVideoEncodeH264OutputModeFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeH264OutputModeFlagsEXT): bool = cint(a) == cint(b) +type + VkVideoEncodeH264RateControlStructureEXT* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT = 0 + VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_FLAT_EXT = 1 + VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_DYADIC_EXT = 2 + VkImageConstraintsInfoFlagBitsFUCHSIA* {.size: sizeof(cint).} = enum + VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA = 0b00000000000000000000000000000001 + VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA = 0b00000000000000000000000000000010 + VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA = 0b00000000000000000000000000000100 + VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA = 0b00000000000000000000000000001000 + VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA = 0b00000000000000000000000000010000 +func toBits*(flags: openArray[VkImageConstraintsInfoFlagBitsFUCHSIA]): VkImageConstraintsInfoFlagsFUCHSIA = + for flag in flags: + result = VkImageConstraintsInfoFlagsFUCHSIA(uint(result) or uint(flag)) +func toEnums*(number: VkImageConstraintsInfoFlagsFUCHSIA): seq[VkImageConstraintsInfoFlagBitsFUCHSIA] = + for value in VkImageConstraintsInfoFlagBitsFUCHSIA.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkImageConstraintsInfoFlagsFUCHSIA): bool = cint(a) == cint(b) +type + VkFormatFeatureFlagBits2* {.size: 8.} = enum + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT = 0b0000000000000000000000000000000000000000000000000000000000000001 + VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT = 0b0000000000000000000000000000000000000000000000000000000000000010 + VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT = 0b0000000000000000000000000000000000000000000000000000000000000100 + VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT = 0b0000000000000000000000000000000000000000000000000000000000001000 + VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT = 0b0000000000000000000000000000000000000000000000000000000000010000 + VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0b0000000000000000000000000000000000000000000000000000000000100000 + VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT = 0b0000000000000000000000000000000000000000000000000000000001000000 + VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT = 0b0000000000000000000000000000000000000000000000000000000010000000 + VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT = 0b0000000000000000000000000000000000000000000000000000000100000000 + VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT = 0b0000000000000000000000000000000000000000000000000000001000000000 + VK_FORMAT_FEATURE_2_BLIT_SRC_BIT = 0b0000000000000000000000000000000000000000000000000000010000000000 + VK_FORMAT_FEATURE_2_BLIT_DST_BIT = 0b0000000000000000000000000000000000000000000000000000100000000000 + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0b0000000000000000000000000000000000000000000000000001000000000000 + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT = 0b0000000000000000000000000000000000000000000000000010000000000000 + VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT = 0b0000000000000000000000000000000000000000000000000100000000000000 + VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT = 0b0000000000000000000000000000000000000000000000001000000000000000 + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0b0000000000000000000000000000000000000000000000010000000000000000 + VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT = 0b0000000000000000000000000000000000000000000000100000000000000000 + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0b0000000000000000000000000000000000000000000001000000000000000000 + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0b0000000000000000000000000000000000000000000010000000000000000000 + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0b0000000000000000000000000000000000000000000100000000000000000000 + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0b0000000000000000000000000000000000000000001000000000000000000000 + VK_FORMAT_FEATURE_2_DISJOINT_BIT = 0b0000000000000000000000000000000000000000010000000000000000000000 + VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT = 0b0000000000000000000000000000000000000000100000000000000000000000 + VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT = 0b0000000000000000000000000000000000000001000000000000000000000000 + VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR = 0b0000000000000000000000000000000000000010000000000000000000000000 + VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR = 0b0000000000000000000000000000000000000100000000000000000000000000 + VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR = 0b0000000000000000000000000000000000001000000000000000000000000000 + VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR = 0b0000000000000000000000000000000000010000000000000000000000000000 + VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0b0000000000000000000000000000000000100000000000000000000000000000 + VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b0000000000000000000000000000000001000000000000000000000000000000 + VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT = 0b0000000000000000000000000000000010000000000000000000000000000000 + VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT = 0b0000000000000000000000000000000100000000000000000000000000000000 + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT = 0b0000000000000000000000000000001000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM = 0b0000000000000000000000000000010000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM = 0b0000000000000000000000000000100000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM = 0b0000000000000000000000000001000000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM = 0b0000000000000000000000000010000000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV = 0b0000000000000000000000000100000000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_RESERVED_39_BIT_EXT = 0b0000000000000000000000001000000000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV = 0b0000000000000000000000010000000000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV = 0b0000000000000000000000100000000000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV = 0b0000000000000000000001000000000000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_RESERVED_44_BIT_EXT = 0b0000000000000000000100000000000000000000000000000000000000000000 + VK_FORMAT_FEATURE_2_RESERVED_45_BIT_EXT = 0b0000000000000000001000000000000000000000000000000000000000000000 +func toBits*(flags: openArray[VkFormatFeatureFlagBits2]): VkFormatFeatureFlags2 = + for flag in flags: + result = VkFormatFeatureFlags2(uint64(result) or uint64(flag)) +func toEnums*(number: VkFormatFeatureFlags2): seq[VkFormatFeatureFlagBits2] = + for value in VkFormatFeatureFlagBits2.items: + if (cast[uint64](value) and uint64(number)) > 0: + result.add value +proc `==`*(a, b: VkFormatFeatureFlags2): bool = uint64(a) == uint64(b) +type + VkRenderingFlagBits* {.size: sizeof(cint).} = enum + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT = 0b00000000000000000000000000000001 + VK_RENDERING_SUSPENDING_BIT = 0b00000000000000000000000000000010 + VK_RENDERING_RESUMING_BIT = 0b00000000000000000000000000000100 + VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkRenderingFlagBits]): VkRenderingFlags = + for flag in flags: + result = VkRenderingFlags(uint(result) or uint(flag)) +func toEnums*(number: VkRenderingFlags): seq[VkRenderingFlagBits] = + for value in VkRenderingFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkRenderingFlags): bool = cint(a) == cint(b) +type + VkVideoEncodeH265CapabilityFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_H265_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_H265_CAPABILITY_SCALING_LISTS_BIT_EXT = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_H265_CAPABILITY_SAMPLE_ADAPTIVE_OFFSET_ENABLED_BIT_EXT = 0b00000000000000000000000000000100 + VK_VIDEO_ENCODE_H265_CAPABILITY_PCM_ENABLE_BIT_EXT = 0b00000000000000000000000000001000 + VK_VIDEO_ENCODE_H265_CAPABILITY_SPS_TEMPORAL_MVP_ENABLED_BIT_EXT = 0b00000000000000000000000000010000 + VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_EXT = 0b00000000000000000000000000100000 + VK_VIDEO_ENCODE_H265_CAPABILITY_INIT_QP_MINUS26_BIT_EXT = 0b00000000000000000000000001000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_EXT = 0b00000000000000000000000010000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_SIGN_DATA_HIDING_ENABLED_BIT_EXT = 0b00000000000000000000000100000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_ENABLED_BIT_EXT = 0b00000000000000000000001000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_DISABLED_BIT_EXT = 0b00000000000000000000010000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_BIT_EXT = 0b00000000000000000000100000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_BIT_EXT = 0b00000000000000000001000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_BIPRED_BIT_EXT = 0b00000000000000000010000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT = 0b00000000000000000100000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSQUANT_BYPASS_ENABLED_BIT_EXT = 0b00000000000000001000000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_ENTROPY_CODING_SYNC_ENABLED_BIT_EXT = 0b00000000000000010000000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_DEBLOCKING_FILTER_OVERRIDE_ENABLED_BIT_EXT = 0b00000000000000100000000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_FRAME_BIT_EXT = 0b00000000000001000000000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_PER_TILE_BIT_EXT = 0b00000000000010000000000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_SLICE_BIT_EXT = 0b00000000000100000000000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_SLICE_SEGMENT_CTB_COUNT_BIT_EXT = 0b00000000001000000000000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_EXT = 0b00000000010000000000000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_DEPENDENT_SLICE_SEGMENT_BIT_EXT = 0b00000000100000000000000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT = 0b00000001000000000000000000000000 + VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0b00000010000000000000000000000000 +func toBits*(flags: openArray[VkVideoEncodeH265CapabilityFlagBitsEXT]): VkVideoEncodeH265CapabilityFlagsEXT = + for flag in flags: + result = VkVideoEncodeH265CapabilityFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeH265CapabilityFlagsEXT): seq[VkVideoEncodeH265CapabilityFlagBitsEXT] = + for value in VkVideoEncodeH265CapabilityFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeH265CapabilityFlagsEXT): bool = cint(a) == cint(b) +type + VkVideoEncodeH265InputModeFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_H265_INPUT_MODE_FRAME_BIT_EXT = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_H265_INPUT_MODE_SLICE_SEGMENT_BIT_EXT = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_H265_INPUT_MODE_NON_VCL_BIT_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkVideoEncodeH265InputModeFlagBitsEXT]): VkVideoEncodeH265InputModeFlagsEXT = + for flag in flags: + result = VkVideoEncodeH265InputModeFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeH265InputModeFlagsEXT): seq[VkVideoEncodeH265InputModeFlagBitsEXT] = + for value in VkVideoEncodeH265InputModeFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeH265InputModeFlagsEXT): bool = cint(a) == cint(b) +type + VkVideoEncodeH265OutputModeFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FRAME_BIT_EXT = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_SLICE_SEGMENT_BIT_EXT = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_NON_VCL_BIT_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkVideoEncodeH265OutputModeFlagBitsEXT]): VkVideoEncodeH265OutputModeFlagsEXT = + for flag in flags: + result = VkVideoEncodeH265OutputModeFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeH265OutputModeFlagsEXT): seq[VkVideoEncodeH265OutputModeFlagBitsEXT] = + for value in VkVideoEncodeH265OutputModeFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeH265OutputModeFlagsEXT): bool = cint(a) == cint(b) +type + VkVideoEncodeH265RateControlStructureEXT* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT = 0 + VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_FLAT_EXT = 1 + VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_DYADIC_EXT = 2 + VkVideoEncodeH265CtbSizeFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_EXT = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkVideoEncodeH265CtbSizeFlagBitsEXT]): VkVideoEncodeH265CtbSizeFlagsEXT = + for flag in flags: + result = VkVideoEncodeH265CtbSizeFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeH265CtbSizeFlagsEXT): seq[VkVideoEncodeH265CtbSizeFlagBitsEXT] = + for value in VkVideoEncodeH265CtbSizeFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeH265CtbSizeFlagsEXT): bool = cint(a) == cint(b) +type + VkVideoEncodeH265TransformBlockSizeFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_EXT = 0b00000000000000000000000000000001 + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_EXT = 0b00000000000000000000000000000010 + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_EXT = 0b00000000000000000000000000000100 + VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_EXT = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkVideoEncodeH265TransformBlockSizeFlagBitsEXT]): VkVideoEncodeH265TransformBlockSizeFlagsEXT = + for flag in flags: + result = VkVideoEncodeH265TransformBlockSizeFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkVideoEncodeH265TransformBlockSizeFlagsEXT): seq[VkVideoEncodeH265TransformBlockSizeFlagBitsEXT] = + for value in VkVideoEncodeH265TransformBlockSizeFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkVideoEncodeH265TransformBlockSizeFlagsEXT): bool = cint(a) == cint(b) +type + VkExportMetalObjectTypeFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT = 0b00000000000000000000000000000001 + VK_EXPORT_METAL_OBJECT_TYPE_METAL_COMMAND_QUEUE_BIT_EXT = 0b00000000000000000000000000000010 + VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT = 0b00000000000000000000000000000100 + VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT = 0b00000000000000000000000000001000 + VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT = 0b00000000000000000000000000010000 + VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT = 0b00000000000000000000000000100000 +func toBits*(flags: openArray[VkExportMetalObjectTypeFlagBitsEXT]): VkExportMetalObjectTypeFlagsEXT = + for flag in flags: + result = VkExportMetalObjectTypeFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkExportMetalObjectTypeFlagsEXT): seq[VkExportMetalObjectTypeFlagBitsEXT] = + for value in VkExportMetalObjectTypeFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkExportMetalObjectTypeFlagsEXT): bool = cint(a) == cint(b) +type + VkInstanceCreateFlagBits* {.size: sizeof(cint).} = enum + VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkInstanceCreateFlagBits]): VkInstanceCreateFlags = + for flag in flags: + result = VkInstanceCreateFlags(uint(result) or uint(flag)) +func toEnums*(number: VkInstanceCreateFlags): seq[VkInstanceCreateFlagBits] = + for value in VkInstanceCreateFlagBits.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkInstanceCreateFlags): bool = cint(a) == cint(b) +type + VkImageCompressionFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT = 0b00000000000000000000000000000001 + VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT = 0b00000000000000000000000000000010 + VK_IMAGE_COMPRESSION_DISABLED_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkImageCompressionFlagBitsEXT]): VkImageCompressionFlagsEXT = + for flag in flags: + result = VkImageCompressionFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkImageCompressionFlagsEXT): seq[VkImageCompressionFlagBitsEXT] = + for value in VkImageCompressionFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkImageCompressionFlagsEXT): bool = cint(a) == cint(b) +const + VK_IMAGE_COMPRESSION_DEFAULT_EXT* = 0 +type + VkImageCompressionFixedRateFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_IMAGE_COMPRESSION_FIXED_RATE_1BPC_BIT_EXT = 0b00000000000000000000000000000001 + VK_IMAGE_COMPRESSION_FIXED_RATE_2BPC_BIT_EXT = 0b00000000000000000000000000000010 + VK_IMAGE_COMPRESSION_FIXED_RATE_3BPC_BIT_EXT = 0b00000000000000000000000000000100 + VK_IMAGE_COMPRESSION_FIXED_RATE_4BPC_BIT_EXT = 0b00000000000000000000000000001000 + VK_IMAGE_COMPRESSION_FIXED_RATE_5BPC_BIT_EXT = 0b00000000000000000000000000010000 + VK_IMAGE_COMPRESSION_FIXED_RATE_6BPC_BIT_EXT = 0b00000000000000000000000000100000 + VK_IMAGE_COMPRESSION_FIXED_RATE_7BPC_BIT_EXT = 0b00000000000000000000000001000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_8BPC_BIT_EXT = 0b00000000000000000000000010000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_9BPC_BIT_EXT = 0b00000000000000000000000100000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_10BPC_BIT_EXT = 0b00000000000000000000001000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_11BPC_BIT_EXT = 0b00000000000000000000010000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_12BPC_BIT_EXT = 0b00000000000000000000100000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_13BPC_BIT_EXT = 0b00000000000000000001000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_14BPC_BIT_EXT = 0b00000000000000000010000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_15BPC_BIT_EXT = 0b00000000000000000100000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_16BPC_BIT_EXT = 0b00000000000000001000000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_17BPC_BIT_EXT = 0b00000000000000010000000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_18BPC_BIT_EXT = 0b00000000000000100000000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_19BPC_BIT_EXT = 0b00000000000001000000000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_20BPC_BIT_EXT = 0b00000000000010000000000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_21BPC_BIT_EXT = 0b00000000000100000000000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_22BPC_BIT_EXT = 0b00000000001000000000000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_23BPC_BIT_EXT = 0b00000000010000000000000000000000 + VK_IMAGE_COMPRESSION_FIXED_RATE_24BPC_BIT_EXT = 0b00000000100000000000000000000000 +func toBits*(flags: openArray[VkImageCompressionFixedRateFlagBitsEXT]): VkImageCompressionFixedRateFlagsEXT = + for flag in flags: + result = VkImageCompressionFixedRateFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkImageCompressionFixedRateFlagsEXT): seq[VkImageCompressionFixedRateFlagBitsEXT] = + for value in VkImageCompressionFixedRateFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkImageCompressionFixedRateFlagsEXT): bool = cint(a) == cint(b) +const + VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT* = 0 +type + VkPipelineRobustnessBufferBehaviorEXT* {.size: sizeof(cint).} = enum + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT = 0 + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT = 1 + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT = 2 + VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT = 3 + VkPipelineRobustnessImageBehaviorEXT* {.size: sizeof(cint).} = enum + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT = 0 + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT = 1 + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_EXT = 2 + VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2_EXT = 3 + VkOpticalFlowGridSizeFlagBitsNV* {.size: sizeof(cint).} = enum + VK_OPTICAL_FLOW_GRID_SIZE_1X1_BIT_NV = 0b00000000000000000000000000000001 + VK_OPTICAL_FLOW_GRID_SIZE_2X2_BIT_NV = 0b00000000000000000000000000000010 + VK_OPTICAL_FLOW_GRID_SIZE_4X4_BIT_NV = 0b00000000000000000000000000000100 + VK_OPTICAL_FLOW_GRID_SIZE_8X8_BIT_NV = 0b00000000000000000000000000001000 +func toBits*(flags: openArray[VkOpticalFlowGridSizeFlagBitsNV]): VkOpticalFlowGridSizeFlagsNV = + for flag in flags: + result = VkOpticalFlowGridSizeFlagsNV(uint(result) or uint(flag)) +func toEnums*(number: VkOpticalFlowGridSizeFlagsNV): seq[VkOpticalFlowGridSizeFlagBitsNV] = + for value in VkOpticalFlowGridSizeFlagBitsNV.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkOpticalFlowGridSizeFlagsNV): bool = cint(a) == cint(b) +const + VK_OPTICAL_FLOW_GRID_SIZE_UNKNOWN_NV* = 0 +type + VkOpticalFlowUsageFlagBitsNV* {.size: sizeof(cint).} = enum + VK_OPTICAL_FLOW_USAGE_INPUT_BIT_NV = 0b00000000000000000000000000000001 + VK_OPTICAL_FLOW_USAGE_OUTPUT_BIT_NV = 0b00000000000000000000000000000010 + VK_OPTICAL_FLOW_USAGE_HINT_BIT_NV = 0b00000000000000000000000000000100 + VK_OPTICAL_FLOW_USAGE_COST_BIT_NV = 0b00000000000000000000000000001000 + VK_OPTICAL_FLOW_USAGE_GLOBAL_FLOW_BIT_NV = 0b00000000000000000000000000010000 +func toBits*(flags: openArray[VkOpticalFlowUsageFlagBitsNV]): VkOpticalFlowUsageFlagsNV = + for flag in flags: + result = VkOpticalFlowUsageFlagsNV(uint(result) or uint(flag)) +func toEnums*(number: VkOpticalFlowUsageFlagsNV): seq[VkOpticalFlowUsageFlagBitsNV] = + for value in VkOpticalFlowUsageFlagBitsNV.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkOpticalFlowUsageFlagsNV): bool = cint(a) == cint(b) +const + VK_OPTICAL_FLOW_USAGE_UNKNOWN_NV* = 0 +type + VkOpticalFlowPerformanceLevelNV* {.size: sizeof(cint).} = enum + VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_UNKNOWN_NV = 0 + VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_SLOW_NV = 1 + VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_MEDIUM_NV = 2 + VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_FAST_NV = 3 + VkOpticalFlowSessionBindingPointNV* {.size: sizeof(cint).} = enum + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_UNKNOWN_NV = 0 + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_INPUT_NV = 1 + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_REFERENCE_NV = 2 + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_HINT_NV = 3 + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_FLOW_VECTOR_NV = 4 + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_BACKWARD_FLOW_VECTOR_NV = 5 + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_COST_NV = 6 + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_BACKWARD_COST_NV = 7 + VK_OPTICAL_FLOW_SESSION_BINDING_POINT_GLOBAL_FLOW_NV = 8 + VkOpticalFlowSessionCreateFlagBitsNV* {.size: sizeof(cint).} = enum + VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_HINT_BIT_NV = 0b00000000000000000000000000000001 + VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_COST_BIT_NV = 0b00000000000000000000000000000010 + VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_GLOBAL_FLOW_BIT_NV = 0b00000000000000000000000000000100 + VK_OPTICAL_FLOW_SESSION_CREATE_ALLOW_REGIONS_BIT_NV = 0b00000000000000000000000000001000 + VK_OPTICAL_FLOW_SESSION_CREATE_BOTH_DIRECTIONS_BIT_NV = 0b00000000000000000000000000010000 +func toBits*(flags: openArray[VkOpticalFlowSessionCreateFlagBitsNV]): VkOpticalFlowSessionCreateFlagsNV = + for flag in flags: + result = VkOpticalFlowSessionCreateFlagsNV(uint(result) or uint(flag)) +func toEnums*(number: VkOpticalFlowSessionCreateFlagsNV): seq[VkOpticalFlowSessionCreateFlagBitsNV] = + for value in VkOpticalFlowSessionCreateFlagBitsNV.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkOpticalFlowSessionCreateFlagsNV): bool = cint(a) == cint(b) +type + VkOpticalFlowExecuteFlagBitsNV* {.size: sizeof(cint).} = enum + VK_OPTICAL_FLOW_EXECUTE_DISABLE_TEMPORAL_HINTS_BIT_NV = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkOpticalFlowExecuteFlagBitsNV]): VkOpticalFlowExecuteFlagsNV = + for flag in flags: + result = VkOpticalFlowExecuteFlagsNV(uint(result) or uint(flag)) +func toEnums*(number: VkOpticalFlowExecuteFlagsNV): seq[VkOpticalFlowExecuteFlagBitsNV] = + for value in VkOpticalFlowExecuteFlagBitsNV.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkOpticalFlowExecuteFlagsNV): bool = cint(a) == cint(b) +type + VkMicromapTypeEXT* {.size: sizeof(cint).} = enum + VK_MICROMAP_TYPE_OPACITY_MICROMAP_EXT = 0 + VkBuildMicromapFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_BUILD_MICROMAP_PREFER_FAST_TRACE_BIT_EXT = 0b00000000000000000000000000000001 + VK_BUILD_MICROMAP_PREFER_FAST_BUILD_BIT_EXT = 0b00000000000000000000000000000010 + VK_BUILD_MICROMAP_ALLOW_COMPACTION_BIT_EXT = 0b00000000000000000000000000000100 +func toBits*(flags: openArray[VkBuildMicromapFlagBitsEXT]): VkBuildMicromapFlagsEXT = + for flag in flags: + result = VkBuildMicromapFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkBuildMicromapFlagsEXT): seq[VkBuildMicromapFlagBitsEXT] = + for value in VkBuildMicromapFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkBuildMicromapFlagsEXT): bool = cint(a) == cint(b) +type + VkMicromapCreateFlagBitsEXT* {.size: sizeof(cint).} = enum + VK_MICROMAP_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000000000000000000001 +func toBits*(flags: openArray[VkMicromapCreateFlagBitsEXT]): VkMicromapCreateFlagsEXT = + for flag in flags: + result = VkMicromapCreateFlagsEXT(uint(result) or uint(flag)) +func toEnums*(number: VkMicromapCreateFlagsEXT): seq[VkMicromapCreateFlagBitsEXT] = + for value in VkMicromapCreateFlagBitsEXT.items: + if (value.ord and cint(number)) > 0: + result.add value +proc `==`*(a, b: VkMicromapCreateFlagsEXT): bool = cint(a) == cint(b) +type + VkCopyMicromapModeEXT* {.size: sizeof(cint).} = enum + VK_COPY_MICROMAP_MODE_CLONE_EXT = 0 + VK_COPY_MICROMAP_MODE_SERIALIZE_EXT = 1 + VK_COPY_MICROMAP_MODE_DESERIALIZE_EXT = 2 + VK_COPY_MICROMAP_MODE_COMPACT_EXT = 3 + VkBuildMicromapModeEXT* {.size: sizeof(cint).} = enum + VK_BUILD_MICROMAP_MODE_BUILD_EXT = 0 + VkOpacityMicromapFormatEXT* {.size: sizeof(cint).} = enum + VK_OPACITY_MICROMAP_FORMAT_2_STATE_EXT = 1 + VK_OPACITY_MICROMAP_FORMAT_4_STATE_EXT = 2 + VkOpacityMicromapSpecialIndexEXT* {.size: sizeof(cint).} = enum + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT = -4 + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT = -3 + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT = -2 + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT = -1 + VkDeviceFaultAddressTypeEXT* {.size: sizeof(cint).} = enum + VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT = 0 + VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT = 1 + VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT = 2 + VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT = 3 + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT = 4 + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT = 5 + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT = 6 + VkDeviceFaultVendorBinaryHeaderVersionEXT* {.size: sizeof(cint).} = enum + VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_EXT_ENUM = 1 +proc `$`*(bitset: VkFramebufferCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkRenderPassCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkSamplerCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkPipelineCacheCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkPipelineShaderStageCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkDescriptorSetLayoutCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkInstanceCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkDeviceQueueCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkBufferCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkBufferUsageFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkColorComponentFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkCommandPoolCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkCommandPoolResetFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkCommandBufferResetFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkCommandBufferUsageFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkCullModeFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkFenceCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkFormatFeatureFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkImageAspectFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkImageCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkImageUsageFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkImageViewCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkMemoryHeapFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkAccessFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkMemoryPropertyFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkPipelineCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkQueryControlFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkQueryPipelineStatisticFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkQueryResultFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkQueueFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkShaderStageFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkSparseMemoryBindFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkStencilFaceFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkPipelineStageFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkSparseImageFormatFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkSampleCountFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkAttachmentDescriptionFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkDescriptorPoolCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkDependencyFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkEventCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkPipelineLayoutCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkIndirectCommandsLayoutUsageFlagsNV): string = $toEnums(bitset) +proc `$`*(bitset: VkIndirectStateFlagsNV): string = $toEnums(bitset) +proc `$`*(bitset: VkPrivateDataSlotCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkSubpassDescriptionFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkResolveModeFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkDescriptorBindingFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkConditionalRenderingFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkGeometryFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkGeometryInstanceFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkBuildAccelerationStructureFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkAccelerationStructureCreateFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkDeviceDiagnosticsConfigFlagsNV): string = $toEnums(bitset) +proc `$`*(bitset: VkPipelineCreationFeedbackFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkPerformanceCounterDescriptionFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkSemaphoreWaitFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkToolPurposeFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkAccessFlags2): string = $toEnums(bitset) +proc `$`*(bitset: VkPipelineStageFlags2): string = $toEnums(bitset) +proc `$`*(bitset: VkImageConstraintsInfoFlagsFUCHSIA): string = $toEnums(bitset) +proc `$`*(bitset: VkFormatFeatureFlags2): string = $toEnums(bitset) +proc `$`*(bitset: VkRenderingFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkPipelineDepthStencilStateCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkPipelineColorBlendStateCreateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkImageCompressionFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkImageCompressionFixedRateFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkExportMetalObjectTypeFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkDeviceAddressBindingFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkBuildMicromapFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkMicromapCreateFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkMemoryDecompressionMethodFlagsNV): string = $toEnums(bitset) +proc `$`*(bitset: VkCompositeAlphaFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkDisplayPlaneAlphaFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkSurfaceTransformFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkDebugReportFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkExternalMemoryHandleTypeFlagsNV): string = $toEnums(bitset) +proc `$`*(bitset: VkExternalMemoryFeatureFlagsNV): string = $toEnums(bitset) +proc `$`*(bitset: VkExternalMemoryHandleTypeFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkExternalMemoryFeatureFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkExternalSemaphoreHandleTypeFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkExternalSemaphoreFeatureFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkSemaphoreImportFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkExternalFenceHandleTypeFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkExternalFenceFeatureFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkFenceImportFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkSurfaceCounterFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkPeerMemoryFeatureFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkMemoryAllocateFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkDeviceGroupPresentModeFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkSwapchainCreateFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkSubgroupFeatureFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkDebugUtilsMessageSeverityFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkDebugUtilsMessageTypeFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkSwapchainImageUsageFlagsANDROID): string = $toEnums(bitset) +proc `$`*(bitset: VkSubmitFlags): string = $toEnums(bitset) +proc `$`*(bitset: VkGraphicsPipelineLibraryFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkOpticalFlowGridSizeFlagsNV): string = $toEnums(bitset) +proc `$`*(bitset: VkOpticalFlowUsageFlagsNV): string = $toEnums(bitset) +proc `$`*(bitset: VkOpticalFlowSessionCreateFlagsNV): string = $toEnums(bitset) +proc `$`*(bitset: VkOpticalFlowExecuteFlagsNV): string = $toEnums(bitset) +proc `$`*(bitset: VkPresentScalingFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkPresentGravityFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoCodecOperationFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoChromaSubsamplingFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoComponentBitDepthFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoCapabilityFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoSessionCreateFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoCodingControlFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoDecodeUsageFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoDecodeCapabilityFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoDecodeH264PictureLayoutFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeUsageFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeContentFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeCapabilityFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeRateControlModeFlagsKHR): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeH264CapabilityFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeH264InputModeFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeH264OutputModeFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeH265CapabilityFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeH265InputModeFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeH265OutputModeFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeH265CtbSizeFlagsEXT): string = $toEnums(bitset) +proc `$`*(bitset: VkVideoEncodeH265TransformBlockSizeFlagsEXT): string = $toEnums(bitset) +type + VkGeometryFlagsNV* = VkGeometryFlagsKHR + VkGeometryInstanceFlagsNV* = VkGeometryInstanceFlagsKHR + VkBuildAccelerationStructureFlagsNV* = VkBuildAccelerationStructureFlagsKHR + VkPrivateDataSlotCreateFlagsEXT* = VkPrivateDataSlotCreateFlags + VkDescriptorUpdateTemplateCreateFlagsKHR* = VkDescriptorUpdateTemplateCreateFlags + VkPipelineCreationFeedbackFlagsEXT* = VkPipelineCreationFeedbackFlags + VkSemaphoreWaitFlagsKHR* = VkSemaphoreWaitFlags + VkAccessFlags2KHR* = VkAccessFlags2 + VkPipelineStageFlags2KHR* = VkPipelineStageFlags2 + VkFormatFeatureFlags2KHR* = VkFormatFeatureFlags2 + VkRenderingFlagsKHR* = VkRenderingFlags + VkPeerMemoryFeatureFlagsKHR* = VkPeerMemoryFeatureFlags + VkMemoryAllocateFlagsKHR* = VkMemoryAllocateFlags + VkCommandPoolTrimFlagsKHR* = VkCommandPoolTrimFlags + VkExternalMemoryHandleTypeFlagsKHR* = VkExternalMemoryHandleTypeFlags + VkExternalMemoryFeatureFlagsKHR* = VkExternalMemoryFeatureFlags + VkExternalSemaphoreHandleTypeFlagsKHR* = VkExternalSemaphoreHandleTypeFlags + VkExternalSemaphoreFeatureFlagsKHR* = VkExternalSemaphoreFeatureFlags + VkSemaphoreImportFlagsKHR* = VkSemaphoreImportFlags + VkExternalFenceHandleTypeFlagsKHR* = VkExternalFenceHandleTypeFlags + VkExternalFenceFeatureFlagsKHR* = VkExternalFenceFeatureFlags + VkFenceImportFlagsKHR* = VkFenceImportFlags + VkDescriptorBindingFlagsEXT* = VkDescriptorBindingFlags + VkResolveModeFlagsKHR* = VkResolveModeFlags + VkToolPurposeFlagsEXT* = VkToolPurposeFlags + VkSubmitFlagsKHR* = VkSubmitFlags + VkPrivateDataSlotCreateFlagBitsEXT* = VkPrivateDataSlotCreateFlagBits + VkDescriptorUpdateTemplateTypeKHR* = VkDescriptorUpdateTemplateType + VkPointClippingBehaviorKHR* = VkPointClippingBehavior + VkQueueGlobalPriorityEXT* = VkQueueGlobalPriorityKHR + VkResolveModeFlagBitsKHR* = VkResolveModeFlagBits + VkDescriptorBindingFlagBitsEXT* = VkDescriptorBindingFlagBits + VkSemaphoreTypeKHR* = VkSemaphoreType + VkGeometryFlagBitsNV* = VkGeometryFlagBitsKHR + VkGeometryInstanceFlagBitsNV* = VkGeometryInstanceFlagBitsKHR + VkBuildAccelerationStructureFlagBitsNV* = VkBuildAccelerationStructureFlagBitsKHR + VkCopyAccelerationStructureModeNV* = VkCopyAccelerationStructureModeKHR + VkAccelerationStructureTypeNV* = VkAccelerationStructureTypeKHR + VkGeometryTypeNV* = VkGeometryTypeKHR + VkRayTracingShaderGroupTypeNV* = VkRayTracingShaderGroupTypeKHR + VkPipelineCreationFeedbackFlagBitsEXT* = VkPipelineCreationFeedbackFlagBits + VkSemaphoreWaitFlagBitsKHR* = VkSemaphoreWaitFlagBits + VkToolPurposeFlagBitsEXT* = VkToolPurposeFlagBits + VkAccessFlagBits2KHR* = VkAccessFlagBits2 + VkPipelineStageFlagBits2KHR* = VkPipelineStageFlagBits2 + VkFormatFeatureFlagBits2KHR* = VkFormatFeatureFlagBits2 + VkRenderingFlagBitsKHR* = VkRenderingFlagBits + VkExternalMemoryHandleTypeFlagBitsKHR* = VkExternalMemoryHandleTypeFlagBits + VkExternalMemoryFeatureFlagBitsKHR* = VkExternalMemoryFeatureFlagBits + VkExternalSemaphoreHandleTypeFlagBitsKHR* = VkExternalSemaphoreHandleTypeFlagBits + VkExternalSemaphoreFeatureFlagBitsKHR* = VkExternalSemaphoreFeatureFlagBits + VkSemaphoreImportFlagBitsKHR* = VkSemaphoreImportFlagBits + VkExternalFenceHandleTypeFlagBitsKHR* = VkExternalFenceHandleTypeFlagBits + VkExternalFenceFeatureFlagBitsKHR* = VkExternalFenceFeatureFlagBits + VkFenceImportFlagBitsKHR* = VkFenceImportFlagBits + VkPeerMemoryFeatureFlagBitsKHR* = VkPeerMemoryFeatureFlagBits + VkMemoryAllocateFlagBitsKHR* = VkMemoryAllocateFlagBits + VkTessellationDomainOriginKHR* = VkTessellationDomainOrigin + VkSamplerYcbcrModelConversionKHR* = VkSamplerYcbcrModelConversion + VkSamplerYcbcrRangeKHR* = VkSamplerYcbcrRange + VkChromaLocationKHR* = VkChromaLocation + VkSamplerReductionModeEXT* = VkSamplerReductionMode + VkShaderFloatControlsIndependenceKHR* = VkShaderFloatControlsIndependence + VkSubmitFlagBitsKHR* = VkSubmitFlagBits + VkDriverIdKHR* = VkDriverId +type + PFN_vkInternalAllocationNotification* = proc(pUserData: pointer, size: csize_t, allocationType: VkInternalAllocationType, allocationScope: VkSystemAllocationScope): void {.cdecl.} + PFN_vkInternalFreeNotification* = proc(pUserData: pointer, size: csize_t, allocationType: VkInternalAllocationType, allocationScope: VkSystemAllocationScope): void {.cdecl.} + PFN_vkReallocationFunction* = proc(pUserData: pointer, pOriginal: pointer, size: csize_t, alignment: csize_t, allocationScope: VkSystemAllocationScope): pointer {.cdecl.} + PFN_vkAllocationFunction* = proc(pUserData: pointer, size: csize_t, alignment: csize_t, allocationScope: VkSystemAllocationScope): pointer {.cdecl.} + PFN_vkFreeFunction* = proc(pUserData: pointer, pMemory: pointer): void {.cdecl.} + PFN_vkVoidFunction* = proc(): void {.cdecl.} + PFN_vkDebugReportCallbackEXT* = proc(flags: VkDebugReportFlagsEXT, objectType: VkDebugReportObjectTypeEXT, theobject: uint64, location: csize_t, messageCode: int32, pLayerPrefix: cstring, pMessage: cstring, pUserData: pointer): VkBool32 {.cdecl.} + PFN_vkDebugUtilsMessengerCallbackEXT* = proc(messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, messageTypes: VkDebugUtilsMessageTypeFlagsEXT, pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT, pUserData: pointer): VkBool32 {.cdecl.} + PFN_vkFaultCallbackFunction* = proc(unrecordedFaults: VkBool32, faultCount: uint32, pFaults: ptr VkFaultData): void {.cdecl.} + PFN_vkDeviceMemoryReportCallbackEXT* = proc(pCallbackData: ptr VkDeviceMemoryReportCallbackDataEXT, pUserData: pointer): void {.cdecl.} + PFN_vkGetInstanceProcAddrLUNARG* = proc(instance: VkInstance, pName: cstring): PFN_vkVoidFunction {.cdecl.} + VkBaseOutStructure* = object + sType*: VkStructureType + pNext*: ptr VkBaseOutStructure + VkBaseInStructure* = object + sType*: VkStructureType + pNext*: ptr VkBaseInStructure + VkOffset2D* = object + x*: int32 + y*: int32 + VkOffset3D* = object + x*: int32 + y*: int32 + z*: int32 + VkExtent2D* = object + width*: uint32 + height*: uint32 + VkExtent3D* = object + width*: uint32 + height*: uint32 + depth*: uint32 + VkViewport* = object + x*: float32 + y*: float32 + width*: float32 + height*: float32 + minDepth*: float32 + maxDepth*: float32 + VkRect2D* = object + offset*: VkOffset2D + extent*: VkExtent2D + VkClearRect* = object + rect*: VkRect2D + baseArrayLayer*: uint32 + layerCount*: uint32 + VkComponentMapping* = object + r*: VkComponentSwizzle + g*: VkComponentSwizzle + b*: VkComponentSwizzle + a*: VkComponentSwizzle + VkPhysicalDeviceProperties* = object + apiVersion*: uint32 + driverVersion*: uint32 + vendorID*: uint32 + deviceID*: uint32 + deviceType*: VkPhysicalDeviceType + deviceName*: array[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, char] + pipelineCacheUUID*: array[VK_UUID_SIZE, uint8] + limits*: VkPhysicalDeviceLimits + sparseProperties*: VkPhysicalDeviceSparseProperties + VkExtensionProperties* = object + extensionName*: array[VK_MAX_EXTENSION_NAME_SIZE, char] + specVersion*: uint32 + VkLayerProperties* = object + layerName*: array[VK_MAX_EXTENSION_NAME_SIZE, char] + specVersion*: uint32 + implementationVersion*: uint32 + description*: array[VK_MAX_DESCRIPTION_SIZE, char] + VkApplicationInfo* = object + sType*: VkStructureType + pNext*: pointer + pApplicationName*: cstring + applicationVersion*: uint32 + pEngineName*: cstring + engineVersion*: uint32 + apiVersion*: uint32 + VkAllocationCallbacks* = object + pUserData*: pointer + pfnAllocation*: PFN_vkAllocationFunction + pfnReallocation*: PFN_vkReallocationFunction + pfnFree*: PFN_vkFreeFunction + pfnInternalAllocation*: PFN_vkInternalAllocationNotification + pfnInternalFree*: PFN_vkInternalFreeNotification + VkDeviceQueueCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDeviceQueueCreateFlags + queueFamilyIndex*: uint32 + queueCount*: uint32 + pQueuePriorities*: ptr float32 + VkDeviceCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDeviceCreateFlags + queueCreateInfoCount*: uint32 + pQueueCreateInfos*: ptr VkDeviceQueueCreateInfo + enabledLayerCount*: uint32 + ppEnabledLayerNames*: cstringArray + enabledExtensionCount*: uint32 + ppEnabledExtensionNames*: cstringArray + pEnabledFeatures*: ptr VkPhysicalDeviceFeatures + VkInstanceCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkInstanceCreateFlags + pApplicationInfo*: ptr VkApplicationInfo + enabledLayerCount*: uint32 + ppEnabledLayerNames*: cstringArray + enabledExtensionCount*: uint32 + ppEnabledExtensionNames*: cstringArray + VkQueueFamilyProperties* = object + queueFlags*: VkQueueFlags + queueCount*: uint32 + timestampValidBits*: uint32 + minImageTransferGranularity*: VkExtent3D + VkPhysicalDeviceMemoryProperties* = object + memoryTypeCount*: uint32 + memoryTypes*: array[VK_MAX_MEMORY_TYPES, VkMemoryType] + memoryHeapCount*: uint32 + memoryHeaps*: array[VK_MAX_MEMORY_HEAPS, VkMemoryHeap] + VkMemoryAllocateInfo* = object + sType*: VkStructureType + pNext*: pointer + allocationSize*: VkDeviceSize + memoryTypeIndex*: uint32 + VkMemoryRequirements* = object + size*: VkDeviceSize + alignment*: VkDeviceSize + memoryTypeBits*: uint32 + VkSparseImageFormatProperties* = object + aspectMask*: VkImageAspectFlags + imageGranularity*: VkExtent3D + flags*: VkSparseImageFormatFlags + VkSparseImageMemoryRequirements* = object + formatProperties*: VkSparseImageFormatProperties + imageMipTailFirstLod*: uint32 + imageMipTailSize*: VkDeviceSize + imageMipTailOffset*: VkDeviceSize + imageMipTailStride*: VkDeviceSize + VkMemoryType* = object + propertyFlags*: VkMemoryPropertyFlags + heapIndex*: uint32 + VkMemoryHeap* = object + size*: VkDeviceSize + flags*: VkMemoryHeapFlags + VkMappedMemoryRange* = object + sType*: VkStructureType + pNext*: pointer + memory*: VkDeviceMemory + offset*: VkDeviceSize + size*: VkDeviceSize + VkFormatProperties* = object + linearTilingFeatures*: VkFormatFeatureFlags + optimalTilingFeatures*: VkFormatFeatureFlags + bufferFeatures*: VkFormatFeatureFlags + VkImageFormatProperties* = object + maxExtent*: VkExtent3D + maxMipLevels*: uint32 + maxArrayLayers*: uint32 + sampleCounts*: VkSampleCountFlags + maxResourceSize*: VkDeviceSize + VkDescriptorBufferInfo* = object + buffer*: VkBuffer + offset*: VkDeviceSize + range*: VkDeviceSize + VkDescriptorImageInfo* = object + sampler*: VkSampler + imageView*: VkImageView + imageLayout*: VkImageLayout + VkWriteDescriptorSet* = object + sType*: VkStructureType + pNext*: pointer + dstSet*: VkDescriptorSet + dstBinding*: uint32 + dstArrayElement*: uint32 + descriptorCount*: uint32 + descriptorType*: VkDescriptorType + pImageInfo*: ptr VkDescriptorImageInfo + pBufferInfo*: ptr VkDescriptorBufferInfo + pTexelBufferView*: ptr VkBufferView + VkCopyDescriptorSet* = object + sType*: VkStructureType + pNext*: pointer + srcSet*: VkDescriptorSet + srcBinding*: uint32 + srcArrayElement*: uint32 + dstSet*: VkDescriptorSet + dstBinding*: uint32 + dstArrayElement*: uint32 + descriptorCount*: uint32 + VkBufferCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkBufferCreateFlags + size*: VkDeviceSize + usage*: VkBufferUsageFlags + sharingMode*: VkSharingMode + queueFamilyIndexCount*: uint32 + pQueueFamilyIndices*: ptr uint32 + VkBufferViewCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkBufferViewCreateFlags + buffer*: VkBuffer + format*: VkFormat + offset*: VkDeviceSize + range*: VkDeviceSize + VkImageSubresource* = object + aspectMask*: VkImageAspectFlags + mipLevel*: uint32 + arrayLayer*: uint32 + VkImageSubresourceLayers* = object + aspectMask*: VkImageAspectFlags + mipLevel*: uint32 + baseArrayLayer*: uint32 + layerCount*: uint32 + VkImageSubresourceRange* = object + aspectMask*: VkImageAspectFlags + baseMipLevel*: uint32 + levelCount*: uint32 + baseArrayLayer*: uint32 + layerCount*: uint32 + VkMemoryBarrier* = object + sType*: VkStructureType + pNext*: pointer + srcAccessMask*: VkAccessFlags + dstAccessMask*: VkAccessFlags + VkBufferMemoryBarrier* = object + sType*: VkStructureType + pNext*: pointer + srcAccessMask*: VkAccessFlags + dstAccessMask*: VkAccessFlags + srcQueueFamilyIndex*: uint32 + dstQueueFamilyIndex*: uint32 + buffer*: VkBuffer + offset*: VkDeviceSize + size*: VkDeviceSize + VkImageMemoryBarrier* = object + sType*: VkStructureType + pNext*: pointer + srcAccessMask*: VkAccessFlags + dstAccessMask*: VkAccessFlags + oldLayout*: VkImageLayout + newLayout*: VkImageLayout + srcQueueFamilyIndex*: uint32 + dstQueueFamilyIndex*: uint32 + image*: VkImage + subresourceRange*: VkImageSubresourceRange + VkImageCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkImageCreateFlags + imageType*: VkImageType + format*: VkFormat + extent*: VkExtent3D + mipLevels*: uint32 + arrayLayers*: uint32 + samples*: VkSampleCountFlagBits + tiling*: VkImageTiling + usage*: VkImageUsageFlags + sharingMode*: VkSharingMode + queueFamilyIndexCount*: uint32 + pQueueFamilyIndices*: ptr uint32 + initialLayout*: VkImageLayout + VkSubresourceLayout* = object + offset*: VkDeviceSize + size*: VkDeviceSize + rowPitch*: VkDeviceSize + arrayPitch*: VkDeviceSize + depthPitch*: VkDeviceSize + VkImageViewCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkImageViewCreateFlags + image*: VkImage + viewType*: VkImageViewType + format*: VkFormat + components*: VkComponentMapping + subresourceRange*: VkImageSubresourceRange + VkBufferCopy* = object + srcOffset*: VkDeviceSize + dstOffset*: VkDeviceSize + size*: VkDeviceSize + VkSparseMemoryBind* = object + resourceOffset*: VkDeviceSize + size*: VkDeviceSize + memory*: VkDeviceMemory + memoryOffset*: VkDeviceSize + flags*: VkSparseMemoryBindFlags + VkSparseImageMemoryBind* = object + subresource*: VkImageSubresource + offset*: VkOffset3D + extent*: VkExtent3D + memory*: VkDeviceMemory + memoryOffset*: VkDeviceSize + flags*: VkSparseMemoryBindFlags + VkSparseBufferMemoryBindInfo* = object + buffer*: VkBuffer + bindCount*: uint32 + pBinds*: ptr VkSparseMemoryBind + VkSparseImageOpaqueMemoryBindInfo* = object + image*: VkImage + bindCount*: uint32 + pBinds*: ptr VkSparseMemoryBind + VkSparseImageMemoryBindInfo* = object + image*: VkImage + bindCount*: uint32 + pBinds*: ptr VkSparseImageMemoryBind + VkBindSparseInfo* = object + sType*: VkStructureType + pNext*: pointer + waitSemaphoreCount*: uint32 + pWaitSemaphores*: ptr VkSemaphore + bufferBindCount*: uint32 + pBufferBinds*: ptr VkSparseBufferMemoryBindInfo + imageOpaqueBindCount*: uint32 + pImageOpaqueBinds*: ptr VkSparseImageOpaqueMemoryBindInfo + imageBindCount*: uint32 + pImageBinds*: ptr VkSparseImageMemoryBindInfo + signalSemaphoreCount*: uint32 + pSignalSemaphores*: ptr VkSemaphore + VkImageCopy* = object + srcSubresource*: VkImageSubresourceLayers + srcOffset*: VkOffset3D + dstSubresource*: VkImageSubresourceLayers + dstOffset*: VkOffset3D + extent*: VkExtent3D + VkImageBlit* = object + srcSubresource*: VkImageSubresourceLayers + srcOffsets*: array[2, VkOffset3D] + dstSubresource*: VkImageSubresourceLayers + dstOffsets*: array[2, VkOffset3D] + VkBufferImageCopy* = object + bufferOffset*: VkDeviceSize + bufferRowLength*: uint32 + bufferImageHeight*: uint32 + imageSubresource*: VkImageSubresourceLayers + imageOffset*: VkOffset3D + imageExtent*: VkExtent3D + VkCopyMemoryIndirectCommandNV* = object + srcAddress*: VkDeviceAddress + dstAddress*: VkDeviceAddress + size*: VkDeviceSize + VkCopyMemoryToImageIndirectCommandNV* = object + srcAddress*: VkDeviceAddress + bufferRowLength*: uint32 + bufferImageHeight*: uint32 + imageSubresource*: VkImageSubresourceLayers + imageOffset*: VkOffset3D + imageExtent*: VkExtent3D + VkImageResolve* = object + srcSubresource*: VkImageSubresourceLayers + srcOffset*: VkOffset3D + dstSubresource*: VkImageSubresourceLayers + dstOffset*: VkOffset3D + extent*: VkExtent3D + VkShaderModuleCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkShaderModuleCreateFlags + codeSize*: csize_t + pCode*: ptr uint32 + VkDescriptorSetLayoutBinding* = object + binding*: uint32 + descriptorType*: VkDescriptorType + descriptorCount*: uint32 + stageFlags*: VkShaderStageFlags + pImmutableSamplers*: ptr VkSampler + VkDescriptorSetLayoutCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDescriptorSetLayoutCreateFlags + bindingCount*: uint32 + pBindings*: ptr VkDescriptorSetLayoutBinding + VkDescriptorPoolSize* = object + thetype*: VkDescriptorType + descriptorCount*: uint32 + VkDescriptorPoolCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDescriptorPoolCreateFlags + maxSets*: uint32 + poolSizeCount*: uint32 + pPoolSizes*: ptr VkDescriptorPoolSize + VkDescriptorSetAllocateInfo* = object + sType*: VkStructureType + pNext*: pointer + descriptorPool*: VkDescriptorPool + descriptorSetCount*: uint32 + pSetLayouts*: ptr VkDescriptorSetLayout + VkSpecializationMapEntry* = object + constantID*: uint32 + offset*: uint32 + size*: csize_t + VkSpecializationInfo* = object + mapEntryCount*: uint32 + pMapEntries*: ptr VkSpecializationMapEntry + dataSize*: csize_t + pData*: pointer + VkPipelineShaderStageCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineShaderStageCreateFlags + stage*: VkShaderStageFlagBits + module*: VkShaderModule + pName*: cstring + pSpecializationInfo*: ptr VkSpecializationInfo + VkComputePipelineCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineCreateFlags + stage*: VkPipelineShaderStageCreateInfo + layout*: VkPipelineLayout + basePipelineHandle*: VkPipeline + basePipelineIndex*: int32 + VkVertexInputBindingDescription* = object + binding*: uint32 + stride*: uint32 + inputRate*: VkVertexInputRate + VkVertexInputAttributeDescription* = object + location*: uint32 + binding*: uint32 + format*: VkFormat + offset*: uint32 + VkPipelineVertexInputStateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineVertexInputStateCreateFlags + vertexBindingDescriptionCount*: uint32 + pVertexBindingDescriptions*: ptr VkVertexInputBindingDescription + vertexAttributeDescriptionCount*: uint32 + pVertexAttributeDescriptions*: ptr VkVertexInputAttributeDescription + VkPipelineInputAssemblyStateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineInputAssemblyStateCreateFlags + topology*: VkPrimitiveTopology + primitiveRestartEnable*: VkBool32 + VkPipelineTessellationStateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineTessellationStateCreateFlags + patchControlPoints*: uint32 + VkPipelineViewportStateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineViewportStateCreateFlags + viewportCount*: uint32 + pViewports*: ptr VkViewport + scissorCount*: uint32 + pScissors*: ptr VkRect2D + VkPipelineRasterizationStateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineRasterizationStateCreateFlags + depthClampEnable*: VkBool32 + rasterizerDiscardEnable*: VkBool32 + polygonMode*: VkPolygonMode + cullMode*: VkCullModeFlags + frontFace*: VkFrontFace + depthBiasEnable*: VkBool32 + depthBiasConstantFactor*: float32 + depthBiasClamp*: float32 + depthBiasSlopeFactor*: float32 + lineWidth*: float32 + VkPipelineMultisampleStateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineMultisampleStateCreateFlags + rasterizationSamples*: VkSampleCountFlagBits + sampleShadingEnable*: VkBool32 + minSampleShading*: float32 + pSampleMask*: ptr VkSampleMask + alphaToCoverageEnable*: VkBool32 + alphaToOneEnable*: VkBool32 + VkPipelineColorBlendAttachmentState* = object + blendEnable*: VkBool32 + srcColorBlendFactor*: VkBlendFactor + dstColorBlendFactor*: VkBlendFactor + colorBlendOp*: VkBlendOp + srcAlphaBlendFactor*: VkBlendFactor + dstAlphaBlendFactor*: VkBlendFactor + alphaBlendOp*: VkBlendOp + colorWriteMask*: VkColorComponentFlags + VkPipelineColorBlendStateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineColorBlendStateCreateFlags + logicOpEnable*: VkBool32 + logicOp*: VkLogicOp + attachmentCount*: uint32 + pAttachments*: ptr VkPipelineColorBlendAttachmentState + blendConstants*: array[4, float32] + VkPipelineDynamicStateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineDynamicStateCreateFlags + dynamicStateCount*: uint32 + pDynamicStates*: ptr VkDynamicState + VkStencilOpState* = object + failOp*: VkStencilOp + passOp*: VkStencilOp + depthFailOp*: VkStencilOp + compareOp*: VkCompareOp + compareMask*: uint32 + writeMask*: uint32 + reference*: uint32 + VkPipelineDepthStencilStateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineDepthStencilStateCreateFlags + depthTestEnable*: VkBool32 + depthWriteEnable*: VkBool32 + depthCompareOp*: VkCompareOp + depthBoundsTestEnable*: VkBool32 + stencilTestEnable*: VkBool32 + front*: VkStencilOpState + back*: VkStencilOpState + minDepthBounds*: float32 + maxDepthBounds*: float32 + VkGraphicsPipelineCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineCreateFlags + stageCount*: uint32 + pStages*: ptr VkPipelineShaderStageCreateInfo + pVertexInputState*: ptr VkPipelineVertexInputStateCreateInfo + pInputAssemblyState*: ptr VkPipelineInputAssemblyStateCreateInfo + pTessellationState*: ptr VkPipelineTessellationStateCreateInfo + pViewportState*: ptr VkPipelineViewportStateCreateInfo + pRasterizationState*: ptr VkPipelineRasterizationStateCreateInfo + pMultisampleState*: ptr VkPipelineMultisampleStateCreateInfo + pDepthStencilState*: ptr VkPipelineDepthStencilStateCreateInfo + pColorBlendState*: ptr VkPipelineColorBlendStateCreateInfo + pDynamicState*: ptr VkPipelineDynamicStateCreateInfo + layout*: VkPipelineLayout + renderPass*: VkRenderPass + subpass*: uint32 + basePipelineHandle*: VkPipeline + basePipelineIndex*: int32 + VkPipelineCacheCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineCacheCreateFlags + initialDataSize*: csize_t + pInitialData*: pointer + VkPipelineCacheHeaderVersionOne* = object + headerSize*: uint32 + headerVersion*: VkPipelineCacheHeaderVersion + vendorID*: uint32 + deviceID*: uint32 + pipelineCacheUUID*: array[VK_UUID_SIZE, uint8] + VkPipelineCacheStageValidationIndexEntry* = object + codeSize*: uint64 + codeOffset*: uint64 + VkPipelineCacheSafetyCriticalIndexEntry* = object + pipelineIdentifier*: array[VK_UUID_SIZE, uint8] + pipelineMemorySize*: uint64 + jsonSize*: uint64 + jsonOffset*: uint64 + stageIndexCount*: uint32 + stageIndexStride*: uint32 + stageIndexOffset*: uint64 + VkPipelineCacheHeaderVersionSafetyCriticalOne* = object + headerVersionOne*: VkPipelineCacheHeaderVersionOne + validationVersion*: VkPipelineCacheValidationVersion + implementationData*: uint32 + pipelineIndexCount*: uint32 + pipelineIndexStride*: uint32 + pipelineIndexOffset*: uint64 + VkPushConstantRange* = object + stageFlags*: VkShaderStageFlags + offset*: uint32 + size*: uint32 + VkPipelineLayoutCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineLayoutCreateFlags + setLayoutCount*: uint32 + pSetLayouts*: ptr VkDescriptorSetLayout + pushConstantRangeCount*: uint32 + pPushConstantRanges*: ptr VkPushConstantRange + VkSamplerCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkSamplerCreateFlags + magFilter*: VkFilter + minFilter*: VkFilter + mipmapMode*: VkSamplerMipmapMode + addressModeU*: VkSamplerAddressMode + addressModeV*: VkSamplerAddressMode + addressModeW*: VkSamplerAddressMode + mipLodBias*: float32 + anisotropyEnable*: VkBool32 + maxAnisotropy*: float32 + compareEnable*: VkBool32 + compareOp*: VkCompareOp + minLod*: float32 + maxLod*: float32 + borderColor*: VkBorderColor + unnormalizedCoordinates*: VkBool32 + VkCommandPoolCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkCommandPoolCreateFlags + queueFamilyIndex*: uint32 + VkCommandBufferAllocateInfo* = object + sType*: VkStructureType + pNext*: pointer + commandPool*: VkCommandPool + level*: VkCommandBufferLevel + commandBufferCount*: uint32 + VkCommandBufferInheritanceInfo* = object + sType*: VkStructureType + pNext*: pointer + renderPass*: VkRenderPass + subpass*: uint32 + framebuffer*: VkFramebuffer + occlusionQueryEnable*: VkBool32 + queryFlags*: VkQueryControlFlags + pipelineStatistics*: VkQueryPipelineStatisticFlags + VkCommandBufferBeginInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkCommandBufferUsageFlags + pInheritanceInfo*: ptr VkCommandBufferInheritanceInfo + VkRenderPassBeginInfo* = object + sType*: VkStructureType + pNext*: pointer + renderPass*: VkRenderPass + framebuffer*: VkFramebuffer + renderArea*: VkRect2D + clearValueCount*: uint32 + pClearValues*: ptr VkClearValue + VkClearColorValue* {.union.} = object + float32*: array[4, float32] + int32*: array[4, int32] + uint32*: array[4, uint32] + VkClearDepthStencilValue* = object + depth*: float32 + stencil*: uint32 + VkClearValue* {.union.} = object + color*: VkClearColorValue + depthStencil*: VkClearDepthStencilValue + VkClearAttachment* = object + aspectMask*: VkImageAspectFlags + colorAttachment*: uint32 + clearValue*: VkClearValue + VkAttachmentDescription* = object + flags*: VkAttachmentDescriptionFlags + format*: VkFormat + samples*: VkSampleCountFlagBits + loadOp*: VkAttachmentLoadOp + storeOp*: VkAttachmentStoreOp + stencilLoadOp*: VkAttachmentLoadOp + stencilStoreOp*: VkAttachmentStoreOp + initialLayout*: VkImageLayout + finalLayout*: VkImageLayout + VkAttachmentReference* = object + attachment*: uint32 + layout*: VkImageLayout + VkSubpassDescription* = object + flags*: VkSubpassDescriptionFlags + pipelineBindPoint*: VkPipelineBindPoint + inputAttachmentCount*: uint32 + pInputAttachments*: ptr VkAttachmentReference + colorAttachmentCount*: uint32 + pColorAttachments*: ptr VkAttachmentReference + pResolveAttachments*: ptr VkAttachmentReference + pDepthStencilAttachment*: ptr VkAttachmentReference + preserveAttachmentCount*: uint32 + pPreserveAttachments*: ptr uint32 + VkSubpassDependency* = object + srcSubpass*: uint32 + dstSubpass*: uint32 + srcStageMask*: VkPipelineStageFlags + dstStageMask*: VkPipelineStageFlags + srcAccessMask*: VkAccessFlags + dstAccessMask*: VkAccessFlags + dependencyFlags*: VkDependencyFlags + VkRenderPassCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkRenderPassCreateFlags + attachmentCount*: uint32 + pAttachments*: ptr VkAttachmentDescription + subpassCount*: uint32 + pSubpasses*: ptr VkSubpassDescription + dependencyCount*: uint32 + pDependencies*: ptr VkSubpassDependency + VkEventCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkEventCreateFlags + VkFenceCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkFenceCreateFlags + VkPhysicalDeviceFeatures* = object + robustBufferAccess*: VkBool32 + fullDrawIndexUint32*: VkBool32 + imageCubeArray*: VkBool32 + independentBlend*: VkBool32 + geometryShader*: VkBool32 + tessellationShader*: VkBool32 + sampleRateShading*: VkBool32 + dualSrcBlend*: VkBool32 + logicOp*: VkBool32 + multiDrawIndirect*: VkBool32 + drawIndirectFirstInstance*: VkBool32 + depthClamp*: VkBool32 + depthBiasClamp*: VkBool32 + fillModeNonSolid*: VkBool32 + depthBounds*: VkBool32 + wideLines*: VkBool32 + largePoints*: VkBool32 + alphaToOne*: VkBool32 + multiViewport*: VkBool32 + samplerAnisotropy*: VkBool32 + textureCompressionETC2*: VkBool32 + textureCompressionASTC_LDR*: VkBool32 + textureCompressionBC*: VkBool32 + occlusionQueryPrecise*: VkBool32 + pipelineStatisticsQuery*: VkBool32 + vertexPipelineStoresAndAtomics*: VkBool32 + fragmentStoresAndAtomics*: VkBool32 + shaderTessellationAndGeometryPointSize*: VkBool32 + shaderImageGatherExtended*: VkBool32 + shaderStorageImageExtendedFormats*: VkBool32 + shaderStorageImageMultisample*: VkBool32 + shaderStorageImageReadWithoutFormat*: VkBool32 + shaderStorageImageWriteWithoutFormat*: VkBool32 + shaderUniformBufferArrayDynamicIndexing*: VkBool32 + shaderSampledImageArrayDynamicIndexing*: VkBool32 + shaderStorageBufferArrayDynamicIndexing*: VkBool32 + shaderStorageImageArrayDynamicIndexing*: VkBool32 + shaderClipDistance*: VkBool32 + shaderCullDistance*: VkBool32 + shaderFloat64*: VkBool32 + shaderInt64*: VkBool32 + shaderInt16*: VkBool32 + shaderResourceResidency*: VkBool32 + shaderResourceMinLod*: VkBool32 + sparseBinding*: VkBool32 + sparseResidencyBuffer*: VkBool32 + sparseResidencyImage2D*: VkBool32 + sparseResidencyImage3D*: VkBool32 + sparseResidency2Samples*: VkBool32 + sparseResidency4Samples*: VkBool32 + sparseResidency8Samples*: VkBool32 + sparseResidency16Samples*: VkBool32 + sparseResidencyAliased*: VkBool32 + variableMultisampleRate*: VkBool32 + inheritedQueries*: VkBool32 + VkPhysicalDeviceSparseProperties* = object + residencyStandard2DBlockShape*: VkBool32 + residencyStandard2DMultisampleBlockShape*: VkBool32 + residencyStandard3DBlockShape*: VkBool32 + residencyAlignedMipSize*: VkBool32 + residencyNonResidentStrict*: VkBool32 + VkPhysicalDeviceLimits* = object + maxImageDimension1D*: uint32 + maxImageDimension2D*: uint32 + maxImageDimension3D*: uint32 + maxImageDimensionCube*: uint32 + maxImageArrayLayers*: uint32 + maxTexelBufferElements*: uint32 + maxUniformBufferRange*: uint32 + maxStorageBufferRange*: uint32 + maxPushConstantsSize*: uint32 + maxMemoryAllocationCount*: uint32 + maxSamplerAllocationCount*: uint32 + bufferImageGranularity*: VkDeviceSize + sparseAddressSpaceSize*: VkDeviceSize + maxBoundDescriptorSets*: uint32 + maxPerStageDescriptorSamplers*: uint32 + maxPerStageDescriptorUniformBuffers*: uint32 + maxPerStageDescriptorStorageBuffers*: uint32 + maxPerStageDescriptorSampledImages*: uint32 + maxPerStageDescriptorStorageImages*: uint32 + maxPerStageDescriptorInputAttachments*: uint32 + maxPerStageResources*: uint32 + maxDescriptorSetSamplers*: uint32 + maxDescriptorSetUniformBuffers*: uint32 + maxDescriptorSetUniformBuffersDynamic*: uint32 + maxDescriptorSetStorageBuffers*: uint32 + maxDescriptorSetStorageBuffersDynamic*: uint32 + maxDescriptorSetSampledImages*: uint32 + maxDescriptorSetStorageImages*: uint32 + maxDescriptorSetInputAttachments*: uint32 + maxVertexInputAttributes*: uint32 + maxVertexInputBindings*: uint32 + maxVertexInputAttributeOffset*: uint32 + maxVertexInputBindingStride*: uint32 + maxVertexOutputComponents*: uint32 + maxTessellationGenerationLevel*: uint32 + maxTessellationPatchSize*: uint32 + maxTessellationControlPerVertexInputComponents*: uint32 + maxTessellationControlPerVertexOutputComponents*: uint32 + maxTessellationControlPerPatchOutputComponents*: uint32 + maxTessellationControlTotalOutputComponents*: uint32 + maxTessellationEvaluationInputComponents*: uint32 + maxTessellationEvaluationOutputComponents*: uint32 + maxGeometryShaderInvocations*: uint32 + maxGeometryInputComponents*: uint32 + maxGeometryOutputComponents*: uint32 + maxGeometryOutputVertices*: uint32 + maxGeometryTotalOutputComponents*: uint32 + maxFragmentInputComponents*: uint32 + maxFragmentOutputAttachments*: uint32 + maxFragmentDualSrcAttachments*: uint32 + maxFragmentCombinedOutputResources*: uint32 + maxComputeSharedMemorySize*: uint32 + maxComputeWorkGroupCount*: array[3, uint32] + maxComputeWorkGroupInvocations*: uint32 + maxComputeWorkGroupSize*: array[3, uint32] + subPixelPrecisionBits*: uint32 + subTexelPrecisionBits*: uint32 + mipmapPrecisionBits*: uint32 + maxDrawIndexedIndexValue*: uint32 + maxDrawIndirectCount*: uint32 + maxSamplerLodBias*: float32 + maxSamplerAnisotropy*: float32 + maxViewports*: uint32 + maxViewportDimensions*: array[2, uint32] + viewportBoundsRange*: array[2, float32] + viewportSubPixelBits*: uint32 + minMemoryMapAlignment*: csize_t + minTexelBufferOffsetAlignment*: VkDeviceSize + minUniformBufferOffsetAlignment*: VkDeviceSize + minStorageBufferOffsetAlignment*: VkDeviceSize + minTexelOffset*: int32 + maxTexelOffset*: uint32 + minTexelGatherOffset*: int32 + maxTexelGatherOffset*: uint32 + minInterpolationOffset*: float32 + maxInterpolationOffset*: float32 + subPixelInterpolationOffsetBits*: uint32 + maxFramebufferWidth*: uint32 + maxFramebufferHeight*: uint32 + maxFramebufferLayers*: uint32 + framebufferColorSampleCounts*: VkSampleCountFlags + framebufferDepthSampleCounts*: VkSampleCountFlags + framebufferStencilSampleCounts*: VkSampleCountFlags + framebufferNoAttachmentsSampleCounts*: VkSampleCountFlags + maxColorAttachments*: uint32 + sampledImageColorSampleCounts*: VkSampleCountFlags + sampledImageIntegerSampleCounts*: VkSampleCountFlags + sampledImageDepthSampleCounts*: VkSampleCountFlags + sampledImageStencilSampleCounts*: VkSampleCountFlags + storageImageSampleCounts*: VkSampleCountFlags + maxSampleMaskWords*: uint32 + timestampComputeAndGraphics*: VkBool32 + timestampPeriod*: float32 + maxClipDistances*: uint32 + maxCullDistances*: uint32 + maxCombinedClipAndCullDistances*: uint32 + discreteQueuePriorities*: uint32 + pointSizeRange*: array[2, float32] + lineWidthRange*: array[2, float32] + pointSizeGranularity*: float32 + lineWidthGranularity*: float32 + strictLines*: VkBool32 + standardSampleLocations*: VkBool32 + optimalBufferCopyOffsetAlignment*: VkDeviceSize + optimalBufferCopyRowPitchAlignment*: VkDeviceSize + nonCoherentAtomSize*: VkDeviceSize + VkSemaphoreCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkSemaphoreCreateFlags + VkQueryPoolCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkQueryPoolCreateFlags + queryType*: VkQueryType + queryCount*: uint32 + pipelineStatistics*: VkQueryPipelineStatisticFlags + VkFramebufferCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkFramebufferCreateFlags + renderPass*: VkRenderPass + attachmentCount*: uint32 + pAttachments*: ptr VkImageView + width*: uint32 + height*: uint32 + layers*: uint32 + VkDrawIndirectCommand* = object + vertexCount*: uint32 + instanceCount*: uint32 + firstVertex*: uint32 + firstInstance*: uint32 + VkDrawIndexedIndirectCommand* = object + indexCount*: uint32 + instanceCount*: uint32 + firstIndex*: uint32 + vertexOffset*: int32 + firstInstance*: uint32 + VkDispatchIndirectCommand* = object + x*: uint32 + y*: uint32 + z*: uint32 + VkMultiDrawInfoEXT* = object + firstVertex*: uint32 + vertexCount*: uint32 + VkMultiDrawIndexedInfoEXT* = object + firstIndex*: uint32 + indexCount*: uint32 + vertexOffset*: int32 + VkSubmitInfo* = object + sType*: VkStructureType + pNext*: pointer + waitSemaphoreCount*: uint32 + pWaitSemaphores*: ptr VkSemaphore + pWaitDstStageMask*: ptr VkPipelineStageFlags + commandBufferCount*: uint32 + pCommandBuffers*: ptr VkCommandBuffer + signalSemaphoreCount*: uint32 + pSignalSemaphores*: ptr VkSemaphore + VkDisplayPropertiesKHR* = object + display*: VkDisplayKHR + displayName*: cstring + physicalDimensions*: VkExtent2D + physicalResolution*: VkExtent2D + supportedTransforms*: VkSurfaceTransformFlagsKHR + planeReorderPossible*: VkBool32 + persistentContent*: VkBool32 + VkDisplayPlanePropertiesKHR* = object + currentDisplay*: VkDisplayKHR + currentStackIndex*: uint32 + VkDisplayModeParametersKHR* = object + visibleRegion*: VkExtent2D + refreshRate*: uint32 + VkDisplayModePropertiesKHR* = object + displayMode*: VkDisplayModeKHR + parameters*: VkDisplayModeParametersKHR + VkDisplayModeCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDisplayModeCreateFlagsKHR + parameters*: VkDisplayModeParametersKHR + VkDisplayPlaneCapabilitiesKHR* = object + supportedAlpha*: VkDisplayPlaneAlphaFlagsKHR + minSrcPosition*: VkOffset2D + maxSrcPosition*: VkOffset2D + minSrcExtent*: VkExtent2D + maxSrcExtent*: VkExtent2D + minDstPosition*: VkOffset2D + maxDstPosition*: VkOffset2D + minDstExtent*: VkExtent2D + maxDstExtent*: VkExtent2D + VkDisplaySurfaceCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDisplaySurfaceCreateFlagsKHR + displayMode*: VkDisplayModeKHR + planeIndex*: uint32 + planeStackIndex*: uint32 + transform*: VkSurfaceTransformFlagBitsKHR + globalAlpha*: float32 + alphaMode*: VkDisplayPlaneAlphaFlagBitsKHR + imageExtent*: VkExtent2D + VkDisplayPresentInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + srcRect*: VkRect2D + dstRect*: VkRect2D + persistent*: VkBool32 + VkSurfaceCapabilitiesKHR* = object + minImageCount*: uint32 + maxImageCount*: uint32 + currentExtent*: VkExtent2D + minImageExtent*: VkExtent2D + maxImageExtent*: VkExtent2D + maxImageArrayLayers*: uint32 + supportedTransforms*: VkSurfaceTransformFlagsKHR + currentTransform*: VkSurfaceTransformFlagBitsKHR + supportedCompositeAlpha*: VkCompositeAlphaFlagsKHR + supportedUsageFlags*: VkImageUsageFlags + VkSurfaceFormatKHR* = object + format*: VkFormat + colorSpace*: VkColorSpaceKHR + VkSwapchainCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkSwapchainCreateFlagsKHR + surface*: VkSurfaceKHR + minImageCount*: uint32 + imageFormat*: VkFormat + imageColorSpace*: VkColorSpaceKHR + imageExtent*: VkExtent2D + imageArrayLayers*: uint32 + imageUsage*: VkImageUsageFlags + imageSharingMode*: VkSharingMode + queueFamilyIndexCount*: uint32 + pQueueFamilyIndices*: ptr uint32 + preTransform*: VkSurfaceTransformFlagBitsKHR + compositeAlpha*: VkCompositeAlphaFlagBitsKHR + presentMode*: VkPresentModeKHR + clipped*: VkBool32 + oldSwapchain*: VkSwapchainKHR + VkPresentInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + waitSemaphoreCount*: uint32 + pWaitSemaphores*: ptr VkSemaphore + swapchainCount*: uint32 + pSwapchains*: ptr VkSwapchainKHR + pImageIndices*: ptr uint32 + pResults*: ptr VkResult + VkDebugReportCallbackCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDebugReportFlagsEXT + pfnCallback*: PFN_vkDebugReportCallbackEXT + pUserData*: pointer + VkValidationFlagsEXT* = object + sType*: VkStructureType + pNext*: pointer + disabledValidationCheckCount*: uint32 + pDisabledValidationChecks*: ptr VkValidationCheckEXT + VkValidationFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + enabledValidationFeatureCount*: uint32 + pEnabledValidationFeatures*: ptr VkValidationFeatureEnableEXT + disabledValidationFeatureCount*: uint32 + pDisabledValidationFeatures*: ptr VkValidationFeatureDisableEXT + VkApplicationParametersEXT* = object + sType*: VkStructureType + pNext*: pointer + vendorID*: uint32 + deviceID*: uint32 + key*: uint32 + value*: uint64 + VkPipelineRasterizationStateRasterizationOrderAMD* = object + sType*: VkStructureType + pNext*: pointer + rasterizationOrder*: VkRasterizationOrderAMD + VkDebugMarkerObjectNameInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + objectType*: VkDebugReportObjectTypeEXT + theobject*: uint64 + pObjectName*: cstring + VkDebugMarkerObjectTagInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + objectType*: VkDebugReportObjectTypeEXT + theobject*: uint64 + tagName*: uint64 + tagSize*: csize_t + pTag*: pointer + VkDebugMarkerMarkerInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + pMarkerName*: cstring + color*: array[4, float32] + VkDedicatedAllocationImageCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + dedicatedAllocation*: VkBool32 + VkDedicatedAllocationBufferCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + dedicatedAllocation*: VkBool32 + VkDedicatedAllocationMemoryAllocateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + image*: VkImage + buffer*: VkBuffer + VkExternalImageFormatPropertiesNV* = object + imageFormatProperties*: VkImageFormatProperties + externalMemoryFeatures*: VkExternalMemoryFeatureFlagsNV + exportFromImportedHandleTypes*: VkExternalMemoryHandleTypeFlagsNV + compatibleHandleTypes*: VkExternalMemoryHandleTypeFlagsNV + VkExternalMemoryImageCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + handleTypes*: VkExternalMemoryHandleTypeFlagsNV + VkExportMemoryAllocateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + handleTypes*: VkExternalMemoryHandleTypeFlagsNV + VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + deviceGeneratedCommands*: VkBool32 + VkDevicePrivateDataCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + privateDataSlotRequestCount*: uint32 + VkDevicePrivateDataCreateInfoEXT* = object + VkPrivateDataSlotCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPrivateDataSlotCreateFlags + VkPrivateDataSlotCreateInfoEXT* = object + VkPhysicalDevicePrivateDataFeatures* = object + sType*: VkStructureType + pNext*: pointer + privateData*: VkBool32 + VkPhysicalDevicePrivateDataFeaturesEXT* = object + VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + maxGraphicsShaderGroupCount*: uint32 + maxIndirectSequenceCount*: uint32 + maxIndirectCommandsTokenCount*: uint32 + maxIndirectCommandsStreamCount*: uint32 + maxIndirectCommandsTokenOffset*: uint32 + maxIndirectCommandsStreamStride*: uint32 + minSequencesCountBufferOffsetAlignment*: uint32 + minSequencesIndexBufferOffsetAlignment*: uint32 + minIndirectCommandsBufferOffsetAlignment*: uint32 + VkPhysicalDeviceMultiDrawPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + maxMultiDrawCount*: uint32 + VkGraphicsShaderGroupCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + stageCount*: uint32 + pStages*: ptr VkPipelineShaderStageCreateInfo + pVertexInputState*: ptr VkPipelineVertexInputStateCreateInfo + pTessellationState*: ptr VkPipelineTessellationStateCreateInfo + VkGraphicsPipelineShaderGroupsCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + groupCount*: uint32 + pGroups*: ptr VkGraphicsShaderGroupCreateInfoNV + pipelineCount*: uint32 + pPipelines*: ptr VkPipeline + VkBindShaderGroupIndirectCommandNV* = object + groupIndex*: uint32 + VkBindIndexBufferIndirectCommandNV* = object + bufferAddress*: VkDeviceAddress + size*: uint32 + indexType*: VkIndexType + VkBindVertexBufferIndirectCommandNV* = object + bufferAddress*: VkDeviceAddress + size*: uint32 + stride*: uint32 + VkSetStateFlagsIndirectCommandNV* = object + data*: uint32 + VkIndirectCommandsStreamNV* = object + buffer*: VkBuffer + offset*: VkDeviceSize + VkIndirectCommandsLayoutTokenNV* = object + sType*: VkStructureType + pNext*: pointer + tokenType*: VkIndirectCommandsTokenTypeNV + stream*: uint32 + offset*: uint32 + vertexBindingUnit*: uint32 + vertexDynamicStride*: VkBool32 + pushconstantPipelineLayout*: VkPipelineLayout + pushconstantShaderStageFlags*: VkShaderStageFlags + pushconstantOffset*: uint32 + pushconstantSize*: uint32 + indirectStateFlags*: VkIndirectStateFlagsNV + indexTypeCount*: uint32 + pIndexTypes*: ptr VkIndexType + pIndexTypeValues*: ptr uint32 + VkIndirectCommandsLayoutCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkIndirectCommandsLayoutUsageFlagsNV + pipelineBindPoint*: VkPipelineBindPoint + tokenCount*: uint32 + pTokens*: ptr VkIndirectCommandsLayoutTokenNV + streamCount*: uint32 + pStreamStrides*: ptr uint32 + VkGeneratedCommandsInfoNV* = object + sType*: VkStructureType + pNext*: pointer + pipelineBindPoint*: VkPipelineBindPoint + pipeline*: VkPipeline + indirectCommandsLayout*: VkIndirectCommandsLayoutNV + streamCount*: uint32 + pStreams*: ptr VkIndirectCommandsStreamNV + sequencesCount*: uint32 + preprocessBuffer*: VkBuffer + preprocessOffset*: VkDeviceSize + preprocessSize*: VkDeviceSize + sequencesCountBuffer*: VkBuffer + sequencesCountOffset*: VkDeviceSize + sequencesIndexBuffer*: VkBuffer + sequencesIndexOffset*: VkDeviceSize + VkGeneratedCommandsMemoryRequirementsInfoNV* = object + sType*: VkStructureType + pNext*: pointer + pipelineBindPoint*: VkPipelineBindPoint + pipeline*: VkPipeline + indirectCommandsLayout*: VkIndirectCommandsLayoutNV + maxSequencesCount*: uint32 + VkPhysicalDeviceFeatures2* = object + sType*: VkStructureType + pNext*: pointer + features*: VkPhysicalDeviceFeatures + VkPhysicalDeviceFeatures2KHR* = object + VkPhysicalDeviceProperties2* = object + sType*: VkStructureType + pNext*: pointer + properties*: VkPhysicalDeviceProperties + VkPhysicalDeviceProperties2KHR* = object + VkFormatProperties2* = object + sType*: VkStructureType + pNext*: pointer + formatProperties*: VkFormatProperties + VkFormatProperties2KHR* = object + VkImageFormatProperties2* = object + sType*: VkStructureType + pNext*: pointer + imageFormatProperties*: VkImageFormatProperties + VkImageFormatProperties2KHR* = object + VkPhysicalDeviceImageFormatInfo2* = object + sType*: VkStructureType + pNext*: pointer + format*: VkFormat + thetype*: VkImageType + tiling*: VkImageTiling + usage*: VkImageUsageFlags + flags*: VkImageCreateFlags + VkPhysicalDeviceImageFormatInfo2KHR* = object + VkQueueFamilyProperties2* = object + sType*: VkStructureType + pNext*: pointer + queueFamilyProperties*: VkQueueFamilyProperties + VkQueueFamilyProperties2KHR* = object + VkPhysicalDeviceMemoryProperties2* = object + sType*: VkStructureType + pNext*: pointer + memoryProperties*: VkPhysicalDeviceMemoryProperties + VkPhysicalDeviceMemoryProperties2KHR* = object + VkSparseImageFormatProperties2* = object + sType*: VkStructureType + pNext*: pointer + properties*: VkSparseImageFormatProperties + VkSparseImageFormatProperties2KHR* = object + VkPhysicalDeviceSparseImageFormatInfo2* = object + sType*: VkStructureType + pNext*: pointer + format*: VkFormat + thetype*: VkImageType + samples*: VkSampleCountFlagBits + usage*: VkImageUsageFlags + tiling*: VkImageTiling + VkPhysicalDeviceSparseImageFormatInfo2KHR* = object + VkPhysicalDevicePushDescriptorPropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + maxPushDescriptors*: uint32 + VkConformanceVersion* = object + major*: uint8 + minor*: uint8 + subminor*: uint8 + patch*: uint8 + VkConformanceVersionKHR* = object + VkPhysicalDeviceDriverProperties* = object + sType*: VkStructureType + pNext*: pointer + driverID*: VkDriverId + driverName*: array[VK_MAX_DRIVER_NAME_SIZE, char] + driverInfo*: array[VK_MAX_DRIVER_INFO_SIZE, char] + conformanceVersion*: VkConformanceVersion + VkPhysicalDeviceDriverPropertiesKHR* = object + VkPresentRegionsKHR* = object + sType*: VkStructureType + pNext*: pointer + swapchainCount*: uint32 + pRegions*: ptr VkPresentRegionKHR + VkPresentRegionKHR* = object + rectangleCount*: uint32 + pRectangles*: ptr VkRectLayerKHR + VkRectLayerKHR* = object + offset*: VkOffset2D + extent*: VkExtent2D + layer*: uint32 + VkPhysicalDeviceVariablePointersFeatures* = object + sType*: VkStructureType + pNext*: pointer + variablePointersStorageBuffer*: VkBool32 + variablePointers*: VkBool32 + VkPhysicalDeviceVariablePointersFeaturesKHR* = object + VkPhysicalDeviceVariablePointerFeaturesKHR* = object + VkPhysicalDeviceVariablePointerFeatures* = object + VkExternalMemoryProperties* = object + externalMemoryFeatures*: VkExternalMemoryFeatureFlags + exportFromImportedHandleTypes*: VkExternalMemoryHandleTypeFlags + compatibleHandleTypes*: VkExternalMemoryHandleTypeFlags + VkExternalMemoryPropertiesKHR* = object + VkPhysicalDeviceExternalImageFormatInfo* = object + sType*: VkStructureType + pNext*: pointer + handleType*: VkExternalMemoryHandleTypeFlagBits + VkPhysicalDeviceExternalImageFormatInfoKHR* = object + VkExternalImageFormatProperties* = object + sType*: VkStructureType + pNext*: pointer + externalMemoryProperties*: VkExternalMemoryProperties + VkExternalImageFormatPropertiesKHR* = object + VkPhysicalDeviceExternalBufferInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkBufferCreateFlags + usage*: VkBufferUsageFlags + handleType*: VkExternalMemoryHandleTypeFlagBits + VkPhysicalDeviceExternalBufferInfoKHR* = object + VkExternalBufferProperties* = object + sType*: VkStructureType + pNext*: pointer + externalMemoryProperties*: VkExternalMemoryProperties + VkExternalBufferPropertiesKHR* = object + VkPhysicalDeviceIDProperties* = object + sType*: VkStructureType + pNext*: pointer + deviceUUID*: array[VK_UUID_SIZE, uint8] + driverUUID*: array[VK_UUID_SIZE, uint8] + deviceLUID*: array[VK_LUID_SIZE, uint8] + deviceNodeMask*: uint32 + deviceLUIDValid*: VkBool32 + VkPhysicalDeviceIDPropertiesKHR* = object + VkExternalMemoryImageCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + handleTypes*: VkExternalMemoryHandleTypeFlags + VkExternalMemoryImageCreateInfoKHR* = object + VkExternalMemoryBufferCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + handleTypes*: VkExternalMemoryHandleTypeFlags + VkExternalMemoryBufferCreateInfoKHR* = object + VkExportMemoryAllocateInfo* = object + sType*: VkStructureType + pNext*: pointer + handleTypes*: VkExternalMemoryHandleTypeFlags + VkExportMemoryAllocateInfoKHR* = object + VkImportMemoryFdInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + handleType*: VkExternalMemoryHandleTypeFlagBits + fd*: cint + VkMemoryFdPropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + memoryTypeBits*: uint32 + VkMemoryGetFdInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + memory*: VkDeviceMemory + handleType*: VkExternalMemoryHandleTypeFlagBits + VkPhysicalDeviceExternalSemaphoreInfo* = object + sType*: VkStructureType + pNext*: pointer + handleType*: VkExternalSemaphoreHandleTypeFlagBits + VkPhysicalDeviceExternalSemaphoreInfoKHR* = object + VkExternalSemaphoreProperties* = object + sType*: VkStructureType + pNext*: pointer + exportFromImportedHandleTypes*: VkExternalSemaphoreHandleTypeFlags + compatibleHandleTypes*: VkExternalSemaphoreHandleTypeFlags + externalSemaphoreFeatures*: VkExternalSemaphoreFeatureFlags + VkExternalSemaphorePropertiesKHR* = object + VkExportSemaphoreCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + handleTypes*: VkExternalSemaphoreHandleTypeFlags + VkExportSemaphoreCreateInfoKHR* = object + VkImportSemaphoreFdInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + flags*: VkSemaphoreImportFlags + handleType*: VkExternalSemaphoreHandleTypeFlagBits + fd*: cint + VkSemaphoreGetFdInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + handleType*: VkExternalSemaphoreHandleTypeFlagBits + VkPhysicalDeviceExternalFenceInfo* = object + sType*: VkStructureType + pNext*: pointer + handleType*: VkExternalFenceHandleTypeFlagBits + VkPhysicalDeviceExternalFenceInfoKHR* = object + VkExternalFenceProperties* = object + sType*: VkStructureType + pNext*: pointer + exportFromImportedHandleTypes*: VkExternalFenceHandleTypeFlags + compatibleHandleTypes*: VkExternalFenceHandleTypeFlags + externalFenceFeatures*: VkExternalFenceFeatureFlags + VkExternalFencePropertiesKHR* = object + VkExportFenceCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + handleTypes*: VkExternalFenceHandleTypeFlags + VkExportFenceCreateInfoKHR* = object + VkImportFenceFdInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + fence*: VkFence + flags*: VkFenceImportFlags + handleType*: VkExternalFenceHandleTypeFlagBits + fd*: cint + VkFenceGetFdInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + fence*: VkFence + handleType*: VkExternalFenceHandleTypeFlagBits + VkPhysicalDeviceMultiviewFeatures* = object + sType*: VkStructureType + pNext*: pointer + multiview*: VkBool32 + multiviewGeometryShader*: VkBool32 + multiviewTessellationShader*: VkBool32 + VkPhysicalDeviceMultiviewFeaturesKHR* = object + VkPhysicalDeviceMultiviewProperties* = object + sType*: VkStructureType + pNext*: pointer + maxMultiviewViewCount*: uint32 + maxMultiviewInstanceIndex*: uint32 + VkPhysicalDeviceMultiviewPropertiesKHR* = object + VkRenderPassMultiviewCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + subpassCount*: uint32 + pViewMasks*: ptr uint32 + dependencyCount*: uint32 + pViewOffsets*: ptr int32 + correlationMaskCount*: uint32 + pCorrelationMasks*: ptr uint32 + VkRenderPassMultiviewCreateInfoKHR* = object + VkSurfaceCapabilities2EXT* = object + sType*: VkStructureType + pNext*: pointer + minImageCount*: uint32 + maxImageCount*: uint32 + currentExtent*: VkExtent2D + minImageExtent*: VkExtent2D + maxImageExtent*: VkExtent2D + maxImageArrayLayers*: uint32 + supportedTransforms*: VkSurfaceTransformFlagsKHR + currentTransform*: VkSurfaceTransformFlagBitsKHR + supportedCompositeAlpha*: VkCompositeAlphaFlagsKHR + supportedUsageFlags*: VkImageUsageFlags + supportedSurfaceCounters*: VkSurfaceCounterFlagsEXT + VkDisplayPowerInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + powerState*: VkDisplayPowerStateEXT + VkDeviceEventInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + deviceEvent*: VkDeviceEventTypeEXT + VkDisplayEventInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + displayEvent*: VkDisplayEventTypeEXT + VkSwapchainCounterCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + surfaceCounters*: VkSurfaceCounterFlagsEXT + VkPhysicalDeviceGroupProperties* = object + sType*: VkStructureType + pNext*: pointer + physicalDeviceCount*: uint32 + physicalDevices*: array[VK_MAX_DEVICE_GROUP_SIZE, VkPhysicalDevice] + subsetAllocation*: VkBool32 + VkPhysicalDeviceGroupPropertiesKHR* = object + VkMemoryAllocateFlagsInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkMemoryAllocateFlags + deviceMask*: uint32 + VkMemoryAllocateFlagsInfoKHR* = object + VkBindBufferMemoryInfo* = object + sType*: VkStructureType + pNext*: pointer + buffer*: VkBuffer + memory*: VkDeviceMemory + memoryOffset*: VkDeviceSize + VkBindBufferMemoryInfoKHR* = object + VkBindBufferMemoryDeviceGroupInfo* = object + sType*: VkStructureType + pNext*: pointer + deviceIndexCount*: uint32 + pDeviceIndices*: ptr uint32 + VkBindBufferMemoryDeviceGroupInfoKHR* = object + VkBindImageMemoryInfo* = object + sType*: VkStructureType + pNext*: pointer + image*: VkImage + memory*: VkDeviceMemory + memoryOffset*: VkDeviceSize + VkBindImageMemoryInfoKHR* = object + VkBindImageMemoryDeviceGroupInfo* = object + sType*: VkStructureType + pNext*: pointer + deviceIndexCount*: uint32 + pDeviceIndices*: ptr uint32 + splitInstanceBindRegionCount*: uint32 + pSplitInstanceBindRegions*: ptr VkRect2D + VkBindImageMemoryDeviceGroupInfoKHR* = object + VkDeviceGroupRenderPassBeginInfo* = object + sType*: VkStructureType + pNext*: pointer + deviceMask*: uint32 + deviceRenderAreaCount*: uint32 + pDeviceRenderAreas*: ptr VkRect2D + VkDeviceGroupRenderPassBeginInfoKHR* = object + VkDeviceGroupCommandBufferBeginInfo* = object + sType*: VkStructureType + pNext*: pointer + deviceMask*: uint32 + VkDeviceGroupCommandBufferBeginInfoKHR* = object + VkDeviceGroupSubmitInfo* = object + sType*: VkStructureType + pNext*: pointer + waitSemaphoreCount*: uint32 + pWaitSemaphoreDeviceIndices*: ptr uint32 + commandBufferCount*: uint32 + pCommandBufferDeviceMasks*: ptr uint32 + signalSemaphoreCount*: uint32 + pSignalSemaphoreDeviceIndices*: ptr uint32 + VkDeviceGroupSubmitInfoKHR* = object + VkDeviceGroupBindSparseInfo* = object + sType*: VkStructureType + pNext*: pointer + resourceDeviceIndex*: uint32 + memoryDeviceIndex*: uint32 + VkDeviceGroupBindSparseInfoKHR* = object + VkDeviceGroupPresentCapabilitiesKHR* = object + sType*: VkStructureType + pNext*: pointer + presentMask*: array[VK_MAX_DEVICE_GROUP_SIZE, uint32] + modes*: VkDeviceGroupPresentModeFlagsKHR + VkImageSwapchainCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + swapchain*: VkSwapchainKHR + VkBindImageMemorySwapchainInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + swapchain*: VkSwapchainKHR + imageIndex*: uint32 + VkAcquireNextImageInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + swapchain*: VkSwapchainKHR + timeout*: uint64 + semaphore*: VkSemaphore + fence*: VkFence + deviceMask*: uint32 + VkDeviceGroupPresentInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + swapchainCount*: uint32 + pDeviceMasks*: ptr uint32 + mode*: VkDeviceGroupPresentModeFlagBitsKHR + VkDeviceGroupDeviceCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + physicalDeviceCount*: uint32 + pPhysicalDevices*: ptr VkPhysicalDevice + VkDeviceGroupDeviceCreateInfoKHR* = object + VkDeviceGroupSwapchainCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + modes*: VkDeviceGroupPresentModeFlagsKHR + VkDescriptorUpdateTemplateEntry* = object + dstBinding*: uint32 + dstArrayElement*: uint32 + descriptorCount*: uint32 + descriptorType*: VkDescriptorType + offset*: csize_t + stride*: csize_t + VkDescriptorUpdateTemplateEntryKHR* = object + VkDescriptorUpdateTemplateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDescriptorUpdateTemplateCreateFlags + descriptorUpdateEntryCount*: uint32 + pDescriptorUpdateEntries*: ptr VkDescriptorUpdateTemplateEntry + templateType*: VkDescriptorUpdateTemplateType + descriptorSetLayout*: VkDescriptorSetLayout + pipelineBindPoint*: VkPipelineBindPoint + pipelineLayout*: VkPipelineLayout + set*: uint32 + VkDescriptorUpdateTemplateCreateInfoKHR* = object + VkXYColorEXT* = object + x*: float32 + y*: float32 + VkPhysicalDevicePresentIdFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + presentId*: VkBool32 + VkPresentIdKHR* = object + sType*: VkStructureType + pNext*: pointer + swapchainCount*: uint32 + pPresentIds*: ptr uint64 + VkPhysicalDevicePresentWaitFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + presentWait*: VkBool32 + VkHdrMetadataEXT* = object + sType*: VkStructureType + pNext*: pointer + displayPrimaryRed*: VkXYColorEXT + displayPrimaryGreen*: VkXYColorEXT + displayPrimaryBlue*: VkXYColorEXT + whitePoint*: VkXYColorEXT + maxLuminance*: float32 + minLuminance*: float32 + maxContentLightLevel*: float32 + maxFrameAverageLightLevel*: float32 + VkDisplayNativeHdrSurfaceCapabilitiesAMD* = object + sType*: VkStructureType + pNext*: pointer + localDimmingSupport*: VkBool32 + VkSwapchainDisplayNativeHdrCreateInfoAMD* = object + sType*: VkStructureType + pNext*: pointer + localDimmingEnable*: VkBool32 + VkRefreshCycleDurationGOOGLE* = object + refreshDuration*: uint64 + VkPastPresentationTimingGOOGLE* = object + presentID*: uint32 + desiredPresentTime*: uint64 + actualPresentTime*: uint64 + earliestPresentTime*: uint64 + presentMargin*: uint64 + VkPresentTimesInfoGOOGLE* = object + sType*: VkStructureType + pNext*: pointer + swapchainCount*: uint32 + pTimes*: ptr VkPresentTimeGOOGLE + VkPresentTimeGOOGLE* = object + presentID*: uint32 + desiredPresentTime*: uint64 + VkViewportWScalingNV* = object + xcoeff*: float32 + ycoeff*: float32 + VkPipelineViewportWScalingStateCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + viewportWScalingEnable*: VkBool32 + viewportCount*: uint32 + pViewportWScalings*: ptr VkViewportWScalingNV + VkViewportSwizzleNV* = object + x*: VkViewportCoordinateSwizzleNV + y*: VkViewportCoordinateSwizzleNV + z*: VkViewportCoordinateSwizzleNV + w*: VkViewportCoordinateSwizzleNV + VkPipelineViewportSwizzleStateCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineViewportSwizzleStateCreateFlagsNV + viewportCount*: uint32 + pViewportSwizzles*: ptr VkViewportSwizzleNV + VkPhysicalDeviceDiscardRectanglePropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + maxDiscardRectangles*: uint32 + VkPipelineDiscardRectangleStateCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineDiscardRectangleStateCreateFlagsEXT + discardRectangleMode*: VkDiscardRectangleModeEXT + discardRectangleCount*: uint32 + pDiscardRectangles*: ptr VkRect2D + VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX* = object + sType*: VkStructureType + pNext*: pointer + perViewPositionAllComponents*: VkBool32 + VkInputAttachmentAspectReference* = object + subpass*: uint32 + inputAttachmentIndex*: uint32 + aspectMask*: VkImageAspectFlags + VkInputAttachmentAspectReferenceKHR* = object + VkRenderPassInputAttachmentAspectCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + aspectReferenceCount*: uint32 + pAspectReferences*: ptr VkInputAttachmentAspectReference + VkRenderPassInputAttachmentAspectCreateInfoKHR* = object + VkPhysicalDeviceSurfaceInfo2KHR* = object + sType*: VkStructureType + pNext*: pointer + surface*: VkSurfaceKHR + VkSurfaceCapabilities2KHR* = object + sType*: VkStructureType + pNext*: pointer + surfaceCapabilities*: VkSurfaceCapabilitiesKHR + VkSurfaceFormat2KHR* = object + sType*: VkStructureType + pNext*: pointer + surfaceFormat*: VkSurfaceFormatKHR + VkDisplayProperties2KHR* = object + sType*: VkStructureType + pNext*: pointer + displayProperties*: VkDisplayPropertiesKHR + VkDisplayPlaneProperties2KHR* = object + sType*: VkStructureType + pNext*: pointer + displayPlaneProperties*: VkDisplayPlanePropertiesKHR + VkDisplayModeProperties2KHR* = object + sType*: VkStructureType + pNext*: pointer + displayModeProperties*: VkDisplayModePropertiesKHR + VkDisplayPlaneInfo2KHR* = object + sType*: VkStructureType + pNext*: pointer + mode*: VkDisplayModeKHR + planeIndex*: uint32 + VkDisplayPlaneCapabilities2KHR* = object + sType*: VkStructureType + pNext*: pointer + capabilities*: VkDisplayPlaneCapabilitiesKHR + VkSharedPresentSurfaceCapabilitiesKHR* = object + sType*: VkStructureType + pNext*: pointer + sharedPresentSupportedUsageFlags*: VkImageUsageFlags + VkPhysicalDevice16BitStorageFeatures* = object + sType*: VkStructureType + pNext*: pointer + storageBuffer16BitAccess*: VkBool32 + uniformAndStorageBuffer16BitAccess*: VkBool32 + storagePushConstant16*: VkBool32 + storageInputOutput16*: VkBool32 + VkPhysicalDevice16BitStorageFeaturesKHR* = object + VkPhysicalDeviceSubgroupProperties* = object + sType*: VkStructureType + pNext*: pointer + subgroupSize*: uint32 + supportedStages*: VkShaderStageFlags + supportedOperations*: VkSubgroupFeatureFlags + quadOperationsInAllStages*: VkBool32 + VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures* = object + sType*: VkStructureType + pNext*: pointer + shaderSubgroupExtendedTypes*: VkBool32 + VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR* = object + VkBufferMemoryRequirementsInfo2* = object + sType*: VkStructureType + pNext*: pointer + buffer*: VkBuffer + VkBufferMemoryRequirementsInfo2KHR* = object + VkDeviceBufferMemoryRequirements* = object + sType*: VkStructureType + pNext*: pointer + pCreateInfo*: ptr VkBufferCreateInfo + VkDeviceBufferMemoryRequirementsKHR* = object + VkImageMemoryRequirementsInfo2* = object + sType*: VkStructureType + pNext*: pointer + image*: VkImage + VkImageMemoryRequirementsInfo2KHR* = object + VkImageSparseMemoryRequirementsInfo2* = object + sType*: VkStructureType + pNext*: pointer + image*: VkImage + VkImageSparseMemoryRequirementsInfo2KHR* = object + VkDeviceImageMemoryRequirements* = object + sType*: VkStructureType + pNext*: pointer + pCreateInfo*: ptr VkImageCreateInfo + planeAspect*: VkImageAspectFlagBits + VkDeviceImageMemoryRequirementsKHR* = object + VkMemoryRequirements2* = object + sType*: VkStructureType + pNext*: pointer + memoryRequirements*: VkMemoryRequirements + VkMemoryRequirements2KHR* = object + VkSparseImageMemoryRequirements2* = object + sType*: VkStructureType + pNext*: pointer + memoryRequirements*: VkSparseImageMemoryRequirements + VkSparseImageMemoryRequirements2KHR* = object + VkPhysicalDevicePointClippingProperties* = object + sType*: VkStructureType + pNext*: pointer + pointClippingBehavior*: VkPointClippingBehavior + VkPhysicalDevicePointClippingPropertiesKHR* = object + VkMemoryDedicatedRequirements* = object + sType*: VkStructureType + pNext*: pointer + prefersDedicatedAllocation*: VkBool32 + requiresDedicatedAllocation*: VkBool32 + VkMemoryDedicatedRequirementsKHR* = object + VkMemoryDedicatedAllocateInfo* = object + sType*: VkStructureType + pNext*: pointer + image*: VkImage + buffer*: VkBuffer + VkMemoryDedicatedAllocateInfoKHR* = object + VkImageViewUsageCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + usage*: VkImageUsageFlags + VkImageViewSlicedCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + sliceOffset*: uint32 + sliceCount*: uint32 + VkImageViewUsageCreateInfoKHR* = object + VkPipelineTessellationDomainOriginStateCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + domainOrigin*: VkTessellationDomainOrigin + VkPipelineTessellationDomainOriginStateCreateInfoKHR* = object + VkSamplerYcbcrConversionInfo* = object + sType*: VkStructureType + pNext*: pointer + conversion*: VkSamplerYcbcrConversion + VkSamplerYcbcrConversionInfoKHR* = object + VkSamplerYcbcrConversionCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + format*: VkFormat + ycbcrModel*: VkSamplerYcbcrModelConversion + ycbcrRange*: VkSamplerYcbcrRange + components*: VkComponentMapping + xChromaOffset*: VkChromaLocation + yChromaOffset*: VkChromaLocation + chromaFilter*: VkFilter + forceExplicitReconstruction*: VkBool32 + VkSamplerYcbcrConversionCreateInfoKHR* = object + VkBindImagePlaneMemoryInfo* = object + sType*: VkStructureType + pNext*: pointer + planeAspect*: VkImageAspectFlagBits + VkBindImagePlaneMemoryInfoKHR* = object + VkImagePlaneMemoryRequirementsInfo* = object + sType*: VkStructureType + pNext*: pointer + planeAspect*: VkImageAspectFlagBits + VkImagePlaneMemoryRequirementsInfoKHR* = object + VkPhysicalDeviceSamplerYcbcrConversionFeatures* = object + sType*: VkStructureType + pNext*: pointer + samplerYcbcrConversion*: VkBool32 + VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR* = object + VkSamplerYcbcrConversionImageFormatProperties* = object + sType*: VkStructureType + pNext*: pointer + combinedImageSamplerDescriptorCount*: uint32 + VkSamplerYcbcrConversionImageFormatPropertiesKHR* = object + VkTextureLODGatherFormatPropertiesAMD* = object + sType*: VkStructureType + pNext*: pointer + supportsTextureGatherLODBiasAMD*: VkBool32 + VkConditionalRenderingBeginInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + buffer*: VkBuffer + offset*: VkDeviceSize + flags*: VkConditionalRenderingFlagsEXT + VkProtectedSubmitInfo* = object + sType*: VkStructureType + pNext*: pointer + protectedSubmit*: VkBool32 + VkPhysicalDeviceProtectedMemoryFeatures* = object + sType*: VkStructureType + pNext*: pointer + protectedMemory*: VkBool32 + VkPhysicalDeviceProtectedMemoryProperties* = object + sType*: VkStructureType + pNext*: pointer + protectedNoFault*: VkBool32 + VkDeviceQueueInfo2* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDeviceQueueCreateFlags + queueFamilyIndex*: uint32 + queueIndex*: uint32 + VkPipelineCoverageToColorStateCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineCoverageToColorStateCreateFlagsNV + coverageToColorEnable*: VkBool32 + coverageToColorLocation*: uint32 + VkPhysicalDeviceSamplerFilterMinmaxProperties* = object + sType*: VkStructureType + pNext*: pointer + filterMinmaxSingleComponentFormats*: VkBool32 + filterMinmaxImageComponentMapping*: VkBool32 + VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT* = object + VkSampleLocationEXT* = object + x*: float32 + y*: float32 + VkSampleLocationsInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + sampleLocationsPerPixel*: VkSampleCountFlagBits + sampleLocationGridSize*: VkExtent2D + sampleLocationsCount*: uint32 + pSampleLocations*: ptr VkSampleLocationEXT + VkAttachmentSampleLocationsEXT* = object + attachmentIndex*: uint32 + sampleLocationsInfo*: VkSampleLocationsInfoEXT + VkSubpassSampleLocationsEXT* = object + subpassIndex*: uint32 + sampleLocationsInfo*: VkSampleLocationsInfoEXT + VkRenderPassSampleLocationsBeginInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + attachmentInitialSampleLocationsCount*: uint32 + pAttachmentInitialSampleLocations*: ptr VkAttachmentSampleLocationsEXT + postSubpassSampleLocationsCount*: uint32 + pPostSubpassSampleLocations*: ptr VkSubpassSampleLocationsEXT + VkPipelineSampleLocationsStateCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + sampleLocationsEnable*: VkBool32 + sampleLocationsInfo*: VkSampleLocationsInfoEXT + VkPhysicalDeviceSampleLocationsPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + sampleLocationSampleCounts*: VkSampleCountFlags + maxSampleLocationGridSize*: VkExtent2D + sampleLocationCoordinateRange*: array[2, float32] + sampleLocationSubPixelBits*: uint32 + variableSampleLocations*: VkBool32 + VkMultisamplePropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + maxSampleLocationGridSize*: VkExtent2D + VkSamplerReductionModeCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + reductionMode*: VkSamplerReductionMode + VkSamplerReductionModeCreateInfoEXT* = object + VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + advancedBlendCoherentOperations*: VkBool32 + VkPhysicalDeviceMultiDrawFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + multiDraw*: VkBool32 + VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + advancedBlendMaxColorAttachments*: uint32 + advancedBlendIndependentBlend*: VkBool32 + advancedBlendNonPremultipliedSrcColor*: VkBool32 + advancedBlendNonPremultipliedDstColor*: VkBool32 + advancedBlendCorrelatedOverlap*: VkBool32 + advancedBlendAllOperations*: VkBool32 + VkPipelineColorBlendAdvancedStateCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + srcPremultiplied*: VkBool32 + dstPremultiplied*: VkBool32 + blendOverlap*: VkBlendOverlapEXT + VkPhysicalDeviceInlineUniformBlockFeatures* = object + sType*: VkStructureType + pNext*: pointer + inlineUniformBlock*: VkBool32 + descriptorBindingInlineUniformBlockUpdateAfterBind*: VkBool32 + VkPhysicalDeviceInlineUniformBlockFeaturesEXT* = object + VkPhysicalDeviceInlineUniformBlockProperties* = object + sType*: VkStructureType + pNext*: pointer + maxInlineUniformBlockSize*: uint32 + maxPerStageDescriptorInlineUniformBlocks*: uint32 + maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks*: uint32 + maxDescriptorSetInlineUniformBlocks*: uint32 + maxDescriptorSetUpdateAfterBindInlineUniformBlocks*: uint32 + VkPhysicalDeviceInlineUniformBlockPropertiesEXT* = object + VkWriteDescriptorSetInlineUniformBlock* = object + sType*: VkStructureType + pNext*: pointer + dataSize*: uint32 + pData*: pointer + VkWriteDescriptorSetInlineUniformBlockEXT* = object + VkDescriptorPoolInlineUniformBlockCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + maxInlineUniformBlockBindings*: uint32 + VkDescriptorPoolInlineUniformBlockCreateInfoEXT* = object + VkPipelineCoverageModulationStateCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineCoverageModulationStateCreateFlagsNV + coverageModulationMode*: VkCoverageModulationModeNV + coverageModulationTableEnable*: VkBool32 + coverageModulationTableCount*: uint32 + pCoverageModulationTable*: ptr float32 + VkImageFormatListCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + viewFormatCount*: uint32 + pViewFormats*: ptr VkFormat + VkImageFormatListCreateInfoKHR* = object + VkValidationCacheCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkValidationCacheCreateFlagsEXT + initialDataSize*: csize_t + pInitialData*: pointer + VkShaderModuleValidationCacheCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + validationCache*: VkValidationCacheEXT + VkPhysicalDeviceMaintenance3Properties* = object + sType*: VkStructureType + pNext*: pointer + maxPerSetDescriptors*: uint32 + maxMemoryAllocationSize*: VkDeviceSize + VkPhysicalDeviceMaintenance3PropertiesKHR* = object + VkPhysicalDeviceMaintenance4Features* = object + sType*: VkStructureType + pNext*: pointer + maintenance4*: VkBool32 + VkPhysicalDeviceMaintenance4FeaturesKHR* = object + VkPhysicalDeviceMaintenance4Properties* = object + sType*: VkStructureType + pNext*: pointer + maxBufferSize*: VkDeviceSize + VkPhysicalDeviceMaintenance4PropertiesKHR* = object + VkDescriptorSetLayoutSupport* = object + sType*: VkStructureType + pNext*: pointer + supported*: VkBool32 + VkDescriptorSetLayoutSupportKHR* = object + VkPhysicalDeviceShaderDrawParametersFeatures* = object + sType*: VkStructureType + pNext*: pointer + shaderDrawParameters*: VkBool32 + VkPhysicalDeviceShaderDrawParameterFeatures* = object + VkPhysicalDeviceShaderFloat16Int8Features* = object + sType*: VkStructureType + pNext*: pointer + shaderFloat16*: VkBool32 + shaderInt8*: VkBool32 + VkPhysicalDeviceShaderFloat16Int8FeaturesKHR* = object + VkPhysicalDeviceFloat16Int8FeaturesKHR* = object + VkPhysicalDeviceFloatControlsProperties* = object + sType*: VkStructureType + pNext*: pointer + denormBehaviorIndependence*: VkShaderFloatControlsIndependence + roundingModeIndependence*: VkShaderFloatControlsIndependence + shaderSignedZeroInfNanPreserveFloat16*: VkBool32 + shaderSignedZeroInfNanPreserveFloat32*: VkBool32 + shaderSignedZeroInfNanPreserveFloat64*: VkBool32 + shaderDenormPreserveFloat16*: VkBool32 + shaderDenormPreserveFloat32*: VkBool32 + shaderDenormPreserveFloat64*: VkBool32 + shaderDenormFlushToZeroFloat16*: VkBool32 + shaderDenormFlushToZeroFloat32*: VkBool32 + shaderDenormFlushToZeroFloat64*: VkBool32 + shaderRoundingModeRTEFloat16*: VkBool32 + shaderRoundingModeRTEFloat32*: VkBool32 + shaderRoundingModeRTEFloat64*: VkBool32 + shaderRoundingModeRTZFloat16*: VkBool32 + shaderRoundingModeRTZFloat32*: VkBool32 + shaderRoundingModeRTZFloat64*: VkBool32 + VkPhysicalDeviceFloatControlsPropertiesKHR* = object + VkPhysicalDeviceHostQueryResetFeatures* = object + sType*: VkStructureType + pNext*: pointer + hostQueryReset*: VkBool32 + VkPhysicalDeviceHostQueryResetFeaturesEXT* = object + VkShaderResourceUsageAMD* = object + numUsedVgprs*: uint32 + numUsedSgprs*: uint32 + ldsSizePerLocalWorkGroup*: uint32 + ldsUsageSizeInBytes*: csize_t + scratchMemUsageInBytes*: csize_t + VkShaderStatisticsInfoAMD* = object + shaderStageMask*: VkShaderStageFlags + resourceUsage*: VkShaderResourceUsageAMD + numPhysicalVgprs*: uint32 + numPhysicalSgprs*: uint32 + numAvailableVgprs*: uint32 + numAvailableSgprs*: uint32 + computeWorkGroupSize*: array[3, uint32] + VkDeviceQueueGlobalPriorityCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + globalPriority*: VkQueueGlobalPriorityKHR + VkDeviceQueueGlobalPriorityCreateInfoEXT* = object + VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + globalPriorityQuery*: VkBool32 + VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT* = object + VkQueueFamilyGlobalPriorityPropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + priorityCount*: uint32 + priorities*: array[VK_MAX_GLOBAL_PRIORITY_SIZE_KHR, VkQueueGlobalPriorityKHR] + VkQueueFamilyGlobalPriorityPropertiesEXT* = object + VkDebugUtilsObjectNameInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + objectType*: VkObjectType + objectHandle*: uint64 + pObjectName*: cstring + VkDebugUtilsObjectTagInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + objectType*: VkObjectType + objectHandle*: uint64 + tagName*: uint64 + tagSize*: csize_t + pTag*: pointer + VkDebugUtilsLabelEXT* = object + sType*: VkStructureType + pNext*: pointer + pLabelName*: cstring + color*: array[4, float32] + VkDebugUtilsMessengerCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDebugUtilsMessengerCreateFlagsEXT + messageSeverity*: VkDebugUtilsMessageSeverityFlagsEXT + messageType*: VkDebugUtilsMessageTypeFlagsEXT + pfnUserCallback*: PFN_vkDebugUtilsMessengerCallbackEXT + pUserData*: pointer + VkDebugUtilsMessengerCallbackDataEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDebugUtilsMessengerCallbackDataFlagsEXT + pMessageIdName*: cstring + messageIdNumber*: int32 + pMessage*: cstring + queueLabelCount*: uint32 + pQueueLabels*: ptr VkDebugUtilsLabelEXT + cmdBufLabelCount*: uint32 + pCmdBufLabels*: ptr VkDebugUtilsLabelEXT + objectCount*: uint32 + pObjects*: ptr VkDebugUtilsObjectNameInfoEXT + VkPhysicalDeviceDeviceMemoryReportFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + deviceMemoryReport*: VkBool32 + VkDeviceDeviceMemoryReportCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDeviceMemoryReportFlagsEXT + pfnUserCallback*: PFN_vkDeviceMemoryReportCallbackEXT + pUserData*: pointer + VkDeviceMemoryReportCallbackDataEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDeviceMemoryReportFlagsEXT + thetype*: VkDeviceMemoryReportEventTypeEXT + memoryObjectId*: uint64 + size*: VkDeviceSize + objectType*: VkObjectType + objectHandle*: uint64 + heapIndex*: uint32 + VkImportMemoryHostPointerInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + handleType*: VkExternalMemoryHandleTypeFlagBits + pHostPointer*: pointer + VkMemoryHostPointerPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + memoryTypeBits*: uint32 + VkPhysicalDeviceExternalMemoryHostPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + minImportedHostPointerAlignment*: VkDeviceSize + VkPhysicalDeviceConservativeRasterizationPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + primitiveOverestimationSize*: float32 + maxExtraPrimitiveOverestimationSize*: float32 + extraPrimitiveOverestimationSizeGranularity*: float32 + primitiveUnderestimation*: VkBool32 + conservativePointAndLineRasterization*: VkBool32 + degenerateTrianglesRasterized*: VkBool32 + degenerateLinesRasterized*: VkBool32 + fullyCoveredFragmentShaderInputVariable*: VkBool32 + conservativeRasterizationPostDepthCoverage*: VkBool32 + VkCalibratedTimestampInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + timeDomain*: VkTimeDomainEXT + VkPhysicalDeviceShaderCorePropertiesAMD* = object + sType*: VkStructureType + pNext*: pointer + shaderEngineCount*: uint32 + shaderArraysPerEngineCount*: uint32 + computeUnitsPerShaderArray*: uint32 + simdPerComputeUnit*: uint32 + wavefrontsPerSimd*: uint32 + wavefrontSize*: uint32 + sgprsPerSimd*: uint32 + minSgprAllocation*: uint32 + maxSgprAllocation*: uint32 + sgprAllocationGranularity*: uint32 + vgprsPerSimd*: uint32 + minVgprAllocation*: uint32 + maxVgprAllocation*: uint32 + vgprAllocationGranularity*: uint32 + VkPhysicalDeviceShaderCoreProperties2AMD* = object + sType*: VkStructureType + pNext*: pointer + shaderCoreFeatures*: VkShaderCorePropertiesFlagsAMD + activeComputeUnitCount*: uint32 + VkPipelineRasterizationConservativeStateCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineRasterizationConservativeStateCreateFlagsEXT + conservativeRasterizationMode*: VkConservativeRasterizationModeEXT + extraPrimitiveOverestimationSize*: float32 + VkPhysicalDeviceDescriptorIndexingFeatures* = object + sType*: VkStructureType + pNext*: pointer + shaderInputAttachmentArrayDynamicIndexing*: VkBool32 + shaderUniformTexelBufferArrayDynamicIndexing*: VkBool32 + shaderStorageTexelBufferArrayDynamicIndexing*: VkBool32 + shaderUniformBufferArrayNonUniformIndexing*: VkBool32 + shaderSampledImageArrayNonUniformIndexing*: VkBool32 + shaderStorageBufferArrayNonUniformIndexing*: VkBool32 + shaderStorageImageArrayNonUniformIndexing*: VkBool32 + shaderInputAttachmentArrayNonUniformIndexing*: VkBool32 + shaderUniformTexelBufferArrayNonUniformIndexing*: VkBool32 + shaderStorageTexelBufferArrayNonUniformIndexing*: VkBool32 + descriptorBindingUniformBufferUpdateAfterBind*: VkBool32 + descriptorBindingSampledImageUpdateAfterBind*: VkBool32 + descriptorBindingStorageImageUpdateAfterBind*: VkBool32 + descriptorBindingStorageBufferUpdateAfterBind*: VkBool32 + descriptorBindingUniformTexelBufferUpdateAfterBind*: VkBool32 + descriptorBindingStorageTexelBufferUpdateAfterBind*: VkBool32 + descriptorBindingUpdateUnusedWhilePending*: VkBool32 + descriptorBindingPartiallyBound*: VkBool32 + descriptorBindingVariableDescriptorCount*: VkBool32 + runtimeDescriptorArray*: VkBool32 + VkPhysicalDeviceDescriptorIndexingFeaturesEXT* = object + VkPhysicalDeviceDescriptorIndexingProperties* = object + sType*: VkStructureType + pNext*: pointer + maxUpdateAfterBindDescriptorsInAllPools*: uint32 + shaderUniformBufferArrayNonUniformIndexingNative*: VkBool32 + shaderSampledImageArrayNonUniformIndexingNative*: VkBool32 + shaderStorageBufferArrayNonUniformIndexingNative*: VkBool32 + shaderStorageImageArrayNonUniformIndexingNative*: VkBool32 + shaderInputAttachmentArrayNonUniformIndexingNative*: VkBool32 + robustBufferAccessUpdateAfterBind*: VkBool32 + quadDivergentImplicitLod*: VkBool32 + maxPerStageDescriptorUpdateAfterBindSamplers*: uint32 + maxPerStageDescriptorUpdateAfterBindUniformBuffers*: uint32 + maxPerStageDescriptorUpdateAfterBindStorageBuffers*: uint32 + maxPerStageDescriptorUpdateAfterBindSampledImages*: uint32 + maxPerStageDescriptorUpdateAfterBindStorageImages*: uint32 + maxPerStageDescriptorUpdateAfterBindInputAttachments*: uint32 + maxPerStageUpdateAfterBindResources*: uint32 + maxDescriptorSetUpdateAfterBindSamplers*: uint32 + maxDescriptorSetUpdateAfterBindUniformBuffers*: uint32 + maxDescriptorSetUpdateAfterBindUniformBuffersDynamic*: uint32 + maxDescriptorSetUpdateAfterBindStorageBuffers*: uint32 + maxDescriptorSetUpdateAfterBindStorageBuffersDynamic*: uint32 + maxDescriptorSetUpdateAfterBindSampledImages*: uint32 + maxDescriptorSetUpdateAfterBindStorageImages*: uint32 + maxDescriptorSetUpdateAfterBindInputAttachments*: uint32 + VkPhysicalDeviceDescriptorIndexingPropertiesEXT* = object + VkDescriptorSetLayoutBindingFlagsCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + bindingCount*: uint32 + pBindingFlags*: ptr VkDescriptorBindingFlags + VkDescriptorSetLayoutBindingFlagsCreateInfoEXT* = object + VkDescriptorSetVariableDescriptorCountAllocateInfo* = object + sType*: VkStructureType + pNext*: pointer + descriptorSetCount*: uint32 + pDescriptorCounts*: ptr uint32 + VkDescriptorSetVariableDescriptorCountAllocateInfoEXT* = object + VkDescriptorSetVariableDescriptorCountLayoutSupport* = object + sType*: VkStructureType + pNext*: pointer + maxVariableDescriptorCount*: uint32 + VkDescriptorSetVariableDescriptorCountLayoutSupportEXT* = object + VkAttachmentDescription2* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkAttachmentDescriptionFlags + format*: VkFormat + samples*: VkSampleCountFlagBits + loadOp*: VkAttachmentLoadOp + storeOp*: VkAttachmentStoreOp + stencilLoadOp*: VkAttachmentLoadOp + stencilStoreOp*: VkAttachmentStoreOp + initialLayout*: VkImageLayout + finalLayout*: VkImageLayout + VkAttachmentDescription2KHR* = object + VkAttachmentReference2* = object + sType*: VkStructureType + pNext*: pointer + attachment*: uint32 + layout*: VkImageLayout + aspectMask*: VkImageAspectFlags + VkAttachmentReference2KHR* = object + VkSubpassDescription2* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkSubpassDescriptionFlags + pipelineBindPoint*: VkPipelineBindPoint + viewMask*: uint32 + inputAttachmentCount*: uint32 + pInputAttachments*: ptr VkAttachmentReference2 + colorAttachmentCount*: uint32 + pColorAttachments*: ptr VkAttachmentReference2 + pResolveAttachments*: ptr VkAttachmentReference2 + pDepthStencilAttachment*: ptr VkAttachmentReference2 + preserveAttachmentCount*: uint32 + pPreserveAttachments*: ptr uint32 + VkSubpassDescription2KHR* = object + VkSubpassDependency2* = object + sType*: VkStructureType + pNext*: pointer + srcSubpass*: uint32 + dstSubpass*: uint32 + srcStageMask*: VkPipelineStageFlags + dstStageMask*: VkPipelineStageFlags + srcAccessMask*: VkAccessFlags + dstAccessMask*: VkAccessFlags + dependencyFlags*: VkDependencyFlags + viewOffset*: int32 + VkSubpassDependency2KHR* = object + VkRenderPassCreateInfo2* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkRenderPassCreateFlags + attachmentCount*: uint32 + pAttachments*: ptr VkAttachmentDescription2 + subpassCount*: uint32 + pSubpasses*: ptr VkSubpassDescription2 + dependencyCount*: uint32 + pDependencies*: ptr VkSubpassDependency2 + correlatedViewMaskCount*: uint32 + pCorrelatedViewMasks*: ptr uint32 + VkRenderPassCreateInfo2KHR* = object + VkSubpassBeginInfo* = object + sType*: VkStructureType + pNext*: pointer + contents*: VkSubpassContents + VkSubpassBeginInfoKHR* = object + VkSubpassEndInfo* = object + sType*: VkStructureType + pNext*: pointer + VkSubpassEndInfoKHR* = object + VkPhysicalDeviceTimelineSemaphoreFeatures* = object + sType*: VkStructureType + pNext*: pointer + timelineSemaphore*: VkBool32 + VkPhysicalDeviceTimelineSemaphoreFeaturesKHR* = object + VkPhysicalDeviceTimelineSemaphoreProperties* = object + sType*: VkStructureType + pNext*: pointer + maxTimelineSemaphoreValueDifference*: uint64 + VkPhysicalDeviceTimelineSemaphorePropertiesKHR* = object + VkSemaphoreTypeCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + semaphoreType*: VkSemaphoreType + initialValue*: uint64 + VkSemaphoreTypeCreateInfoKHR* = object + VkTimelineSemaphoreSubmitInfo* = object + sType*: VkStructureType + pNext*: pointer + waitSemaphoreValueCount*: uint32 + pWaitSemaphoreValues*: ptr uint64 + signalSemaphoreValueCount*: uint32 + pSignalSemaphoreValues*: ptr uint64 + VkTimelineSemaphoreSubmitInfoKHR* = object + VkSemaphoreWaitInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkSemaphoreWaitFlags + semaphoreCount*: uint32 + pSemaphores*: ptr VkSemaphore + pValues*: ptr uint64 + VkSemaphoreWaitInfoKHR* = object + VkSemaphoreSignalInfo* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + value*: uint64 + VkSemaphoreSignalInfoKHR* = object + VkVertexInputBindingDivisorDescriptionEXT* = object + binding*: uint32 + divisor*: uint32 + VkPipelineVertexInputDivisorStateCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + vertexBindingDivisorCount*: uint32 + pVertexBindingDivisors*: ptr VkVertexInputBindingDivisorDescriptionEXT + VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + maxVertexAttribDivisor*: uint32 + VkPhysicalDevicePCIBusInfoPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + pciDomain*: uint32 + pciBus*: uint32 + pciDevice*: uint32 + pciFunction*: uint32 + VkCommandBufferInheritanceConditionalRenderingInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + conditionalRenderingEnable*: VkBool32 + VkPhysicalDevice8BitStorageFeatures* = object + sType*: VkStructureType + pNext*: pointer + storageBuffer8BitAccess*: VkBool32 + uniformAndStorageBuffer8BitAccess*: VkBool32 + storagePushConstant8*: VkBool32 + VkPhysicalDevice8BitStorageFeaturesKHR* = object + VkPhysicalDeviceConditionalRenderingFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + conditionalRendering*: VkBool32 + inheritedConditionalRendering*: VkBool32 + VkPhysicalDeviceVulkanMemoryModelFeatures* = object + sType*: VkStructureType + pNext*: pointer + vulkanMemoryModel*: VkBool32 + vulkanMemoryModelDeviceScope*: VkBool32 + vulkanMemoryModelAvailabilityVisibilityChains*: VkBool32 + VkPhysicalDeviceVulkanMemoryModelFeaturesKHR* = object + VkPhysicalDeviceShaderAtomicInt64Features* = object + sType*: VkStructureType + pNext*: pointer + shaderBufferInt64Atomics*: VkBool32 + shaderSharedInt64Atomics*: VkBool32 + VkPhysicalDeviceShaderAtomicInt64FeaturesKHR* = object + VkPhysicalDeviceShaderAtomicFloatFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + shaderBufferFloat32Atomics*: VkBool32 + shaderBufferFloat32AtomicAdd*: VkBool32 + shaderBufferFloat64Atomics*: VkBool32 + shaderBufferFloat64AtomicAdd*: VkBool32 + shaderSharedFloat32Atomics*: VkBool32 + shaderSharedFloat32AtomicAdd*: VkBool32 + shaderSharedFloat64Atomics*: VkBool32 + shaderSharedFloat64AtomicAdd*: VkBool32 + shaderImageFloat32Atomics*: VkBool32 + shaderImageFloat32AtomicAdd*: VkBool32 + sparseImageFloat32Atomics*: VkBool32 + sparseImageFloat32AtomicAdd*: VkBool32 + VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + shaderBufferFloat16Atomics*: VkBool32 + shaderBufferFloat16AtomicAdd*: VkBool32 + shaderBufferFloat16AtomicMinMax*: VkBool32 + shaderBufferFloat32AtomicMinMax*: VkBool32 + shaderBufferFloat64AtomicMinMax*: VkBool32 + shaderSharedFloat16Atomics*: VkBool32 + shaderSharedFloat16AtomicAdd*: VkBool32 + shaderSharedFloat16AtomicMinMax*: VkBool32 + shaderSharedFloat32AtomicMinMax*: VkBool32 + shaderSharedFloat64AtomicMinMax*: VkBool32 + shaderImageFloat32AtomicMinMax*: VkBool32 + sparseImageFloat32AtomicMinMax*: VkBool32 + VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + vertexAttributeInstanceRateDivisor*: VkBool32 + vertexAttributeInstanceRateZeroDivisor*: VkBool32 + VkQueueFamilyCheckpointPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + checkpointExecutionStageMask*: VkPipelineStageFlags + VkCheckpointDataNV* = object + sType*: VkStructureType + pNext*: pointer + stage*: VkPipelineStageFlagBits + pCheckpointMarker*: pointer + VkPhysicalDeviceDepthStencilResolveProperties* = object + sType*: VkStructureType + pNext*: pointer + supportedDepthResolveModes*: VkResolveModeFlags + supportedStencilResolveModes*: VkResolveModeFlags + independentResolveNone*: VkBool32 + independentResolve*: VkBool32 + VkPhysicalDeviceDepthStencilResolvePropertiesKHR* = object + VkSubpassDescriptionDepthStencilResolve* = object + sType*: VkStructureType + pNext*: pointer + depthResolveMode*: VkResolveModeFlagBits + stencilResolveMode*: VkResolveModeFlagBits + pDepthStencilResolveAttachment*: ptr VkAttachmentReference2 + VkSubpassDescriptionDepthStencilResolveKHR* = object + VkImageViewASTCDecodeModeEXT* = object + sType*: VkStructureType + pNext*: pointer + decodeMode*: VkFormat + VkPhysicalDeviceASTCDecodeFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + decodeModeSharedExponent*: VkBool32 + VkPhysicalDeviceTransformFeedbackFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + transformFeedback*: VkBool32 + geometryStreams*: VkBool32 + VkPhysicalDeviceTransformFeedbackPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + maxTransformFeedbackStreams*: uint32 + maxTransformFeedbackBuffers*: uint32 + maxTransformFeedbackBufferSize*: VkDeviceSize + maxTransformFeedbackStreamDataSize*: uint32 + maxTransformFeedbackBufferDataSize*: uint32 + maxTransformFeedbackBufferDataStride*: uint32 + transformFeedbackQueries*: VkBool32 + transformFeedbackStreamsLinesTriangles*: VkBool32 + transformFeedbackRasterizationStreamSelect*: VkBool32 + transformFeedbackDraw*: VkBool32 + VkPipelineRasterizationStateStreamCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineRasterizationStateStreamCreateFlagsEXT + rasterizationStream*: uint32 + VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + representativeFragmentTest*: VkBool32 + VkPipelineRepresentativeFragmentTestStateCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + representativeFragmentTestEnable*: VkBool32 + VkPhysicalDeviceExclusiveScissorFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + exclusiveScissor*: VkBool32 + VkPipelineViewportExclusiveScissorStateCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + exclusiveScissorCount*: uint32 + pExclusiveScissors*: ptr VkRect2D + VkPhysicalDeviceCornerSampledImageFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + cornerSampledImage*: VkBool32 + VkPhysicalDeviceComputeShaderDerivativesFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + computeDerivativeGroupQuads*: VkBool32 + computeDerivativeGroupLinear*: VkBool32 + VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV* = object + VkPhysicalDeviceShaderImageFootprintFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + imageFootprint*: VkBool32 + VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + dedicatedAllocationImageAliasing*: VkBool32 + VkPhysicalDeviceCopyMemoryIndirectFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + indirectCopy*: VkBool32 + VkPhysicalDeviceCopyMemoryIndirectPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + supportedQueues*: VkQueueFlags + VkPhysicalDeviceMemoryDecompressionFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + memoryDecompression*: VkBool32 + VkPhysicalDeviceMemoryDecompressionPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + decompressionMethods*: VkMemoryDecompressionMethodFlagsNV + maxDecompressionIndirectCount*: uint64 + VkShadingRatePaletteNV* = object + shadingRatePaletteEntryCount*: uint32 + pShadingRatePaletteEntries*: ptr VkShadingRatePaletteEntryNV + VkPipelineViewportShadingRateImageStateCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + shadingRateImageEnable*: VkBool32 + viewportCount*: uint32 + pShadingRatePalettes*: ptr VkShadingRatePaletteNV + VkPhysicalDeviceShadingRateImageFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + shadingRateImage*: VkBool32 + shadingRateCoarseSampleOrder*: VkBool32 + VkPhysicalDeviceShadingRateImagePropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + shadingRateTexelSize*: VkExtent2D + shadingRatePaletteSize*: uint32 + shadingRateMaxCoarseSamples*: uint32 + VkPhysicalDeviceInvocationMaskFeaturesHUAWEI* = object + sType*: VkStructureType + pNext*: pointer + invocationMask*: VkBool32 + VkCoarseSampleLocationNV* = object + pixelX*: uint32 + pixelY*: uint32 + sample*: uint32 + VkCoarseSampleOrderCustomNV* = object + shadingRate*: VkShadingRatePaletteEntryNV + sampleCount*: uint32 + sampleLocationCount*: uint32 + pSampleLocations*: ptr VkCoarseSampleLocationNV + VkPipelineViewportCoarseSampleOrderStateCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + sampleOrderType*: VkCoarseSampleOrderTypeNV + customSampleOrderCount*: uint32 + pCustomSampleOrders*: ptr VkCoarseSampleOrderCustomNV + VkPhysicalDeviceMeshShaderFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + taskShader*: VkBool32 + meshShader*: VkBool32 + VkPhysicalDeviceMeshShaderPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + maxDrawMeshTasksCount*: uint32 + maxTaskWorkGroupInvocations*: uint32 + maxTaskWorkGroupSize*: array[3, uint32] + maxTaskTotalMemorySize*: uint32 + maxTaskOutputCount*: uint32 + maxMeshWorkGroupInvocations*: uint32 + maxMeshWorkGroupSize*: array[3, uint32] + maxMeshTotalMemorySize*: uint32 + maxMeshOutputVertices*: uint32 + maxMeshOutputPrimitives*: uint32 + maxMeshMultiviewViewCount*: uint32 + meshOutputPerVertexGranularity*: uint32 + meshOutputPerPrimitiveGranularity*: uint32 + VkDrawMeshTasksIndirectCommandNV* = object + taskCount*: uint32 + firstTask*: uint32 + VkPhysicalDeviceMeshShaderFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + taskShader*: VkBool32 + meshShader*: VkBool32 + multiviewMeshShader*: VkBool32 + primitiveFragmentShadingRateMeshShader*: VkBool32 + meshShaderQueries*: VkBool32 + VkPhysicalDeviceMeshShaderPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + maxTaskWorkGroupTotalCount*: uint32 + maxTaskWorkGroupCount*: array[3, uint32] + maxTaskWorkGroupInvocations*: uint32 + maxTaskWorkGroupSize*: array[3, uint32] + maxTaskPayloadSize*: uint32 + maxTaskSharedMemorySize*: uint32 + maxTaskPayloadAndSharedMemorySize*: uint32 + maxMeshWorkGroupTotalCount*: uint32 + maxMeshWorkGroupCount*: array[3, uint32] + maxMeshWorkGroupInvocations*: uint32 + maxMeshWorkGroupSize*: array[3, uint32] + maxMeshSharedMemorySize*: uint32 + maxMeshPayloadAndSharedMemorySize*: uint32 + maxMeshOutputMemorySize*: uint32 + maxMeshPayloadAndOutputMemorySize*: uint32 + maxMeshOutputComponents*: uint32 + maxMeshOutputVertices*: uint32 + maxMeshOutputPrimitives*: uint32 + maxMeshOutputLayers*: uint32 + maxMeshMultiviewViewCount*: uint32 + meshOutputPerVertexGranularity*: uint32 + meshOutputPerPrimitiveGranularity*: uint32 + maxPreferredTaskWorkGroupInvocations*: uint32 + maxPreferredMeshWorkGroupInvocations*: uint32 + prefersLocalInvocationVertexOutput*: VkBool32 + prefersLocalInvocationPrimitiveOutput*: VkBool32 + prefersCompactVertexOutput*: VkBool32 + prefersCompactPrimitiveOutput*: VkBool32 + VkDrawMeshTasksIndirectCommandEXT* = object + groupCountX*: uint32 + groupCountY*: uint32 + groupCountZ*: uint32 + VkRayTracingShaderGroupCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + thetype*: VkRayTracingShaderGroupTypeKHR + generalShader*: uint32 + closestHitShader*: uint32 + anyHitShader*: uint32 + intersectionShader*: uint32 + VkRayTracingShaderGroupCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + thetype*: VkRayTracingShaderGroupTypeKHR + generalShader*: uint32 + closestHitShader*: uint32 + anyHitShader*: uint32 + intersectionShader*: uint32 + pShaderGroupCaptureReplayHandle*: pointer + VkRayTracingPipelineCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineCreateFlags + stageCount*: uint32 + pStages*: ptr VkPipelineShaderStageCreateInfo + groupCount*: uint32 + pGroups*: ptr VkRayTracingShaderGroupCreateInfoNV + maxRecursionDepth*: uint32 + layout*: VkPipelineLayout + basePipelineHandle*: VkPipeline + basePipelineIndex*: int32 + VkRayTracingPipelineCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineCreateFlags + stageCount*: uint32 + pStages*: ptr VkPipelineShaderStageCreateInfo + groupCount*: uint32 + pGroups*: ptr VkRayTracingShaderGroupCreateInfoKHR + maxPipelineRayRecursionDepth*: uint32 + pLibraryInfo*: ptr VkPipelineLibraryCreateInfoKHR + pLibraryInterface*: ptr VkRayTracingPipelineInterfaceCreateInfoKHR + pDynamicState*: ptr VkPipelineDynamicStateCreateInfo + layout*: VkPipelineLayout + basePipelineHandle*: VkPipeline + basePipelineIndex*: int32 + VkGeometryTrianglesNV* = object + sType*: VkStructureType + pNext*: pointer + vertexData*: VkBuffer + vertexOffset*: VkDeviceSize + vertexCount*: uint32 + vertexStride*: VkDeviceSize + vertexFormat*: VkFormat + indexData*: VkBuffer + indexOffset*: VkDeviceSize + indexCount*: uint32 + indexType*: VkIndexType + transformData*: VkBuffer + transformOffset*: VkDeviceSize + VkGeometryAABBNV* = object + sType*: VkStructureType + pNext*: pointer + aabbData*: VkBuffer + numAABBs*: uint32 + stride*: uint32 + offset*: VkDeviceSize + VkGeometryDataNV* = object + triangles*: VkGeometryTrianglesNV + aabbs*: VkGeometryAABBNV + VkGeometryNV* = object + sType*: VkStructureType + pNext*: pointer + geometryType*: VkGeometryTypeKHR + geometry*: VkGeometryDataNV + flags*: VkGeometryFlagsKHR + VkAccelerationStructureInfoNV* = object + sType*: VkStructureType + pNext*: pointer + thetype*: VkAccelerationStructureTypeNV + flags*: VkBuildAccelerationStructureFlagsNV + instanceCount*: uint32 + geometryCount*: uint32 + pGeometries*: ptr VkGeometryNV + VkAccelerationStructureCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + compactedSize*: VkDeviceSize + info*: VkAccelerationStructureInfoNV + VkBindAccelerationStructureMemoryInfoNV* = object + sType*: VkStructureType + pNext*: pointer + accelerationStructure*: VkAccelerationStructureNV + memory*: VkDeviceMemory + memoryOffset*: VkDeviceSize + deviceIndexCount*: uint32 + pDeviceIndices*: ptr uint32 + VkWriteDescriptorSetAccelerationStructureKHR* = object + sType*: VkStructureType + pNext*: pointer + accelerationStructureCount*: uint32 + pAccelerationStructures*: ptr VkAccelerationStructureKHR + VkWriteDescriptorSetAccelerationStructureNV* = object + sType*: VkStructureType + pNext*: pointer + accelerationStructureCount*: uint32 + pAccelerationStructures*: ptr VkAccelerationStructureNV + VkAccelerationStructureMemoryRequirementsInfoNV* = object + sType*: VkStructureType + pNext*: pointer + thetype*: VkAccelerationStructureMemoryRequirementsTypeNV + accelerationStructure*: VkAccelerationStructureNV + VkPhysicalDeviceAccelerationStructureFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + accelerationStructure*: VkBool32 + accelerationStructureCaptureReplay*: VkBool32 + accelerationStructureIndirectBuild*: VkBool32 + accelerationStructureHostCommands*: VkBool32 + descriptorBindingAccelerationStructureUpdateAfterBind*: VkBool32 + VkPhysicalDeviceRayTracingPipelineFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + rayTracingPipeline*: VkBool32 + rayTracingPipelineShaderGroupHandleCaptureReplay*: VkBool32 + rayTracingPipelineShaderGroupHandleCaptureReplayMixed*: VkBool32 + rayTracingPipelineTraceRaysIndirect*: VkBool32 + rayTraversalPrimitiveCulling*: VkBool32 + VkPhysicalDeviceRayQueryFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + rayQuery*: VkBool32 + VkPhysicalDeviceAccelerationStructurePropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + maxGeometryCount*: uint64 + maxInstanceCount*: uint64 + maxPrimitiveCount*: uint64 + maxPerStageDescriptorAccelerationStructures*: uint32 + maxPerStageDescriptorUpdateAfterBindAccelerationStructures*: uint32 + maxDescriptorSetAccelerationStructures*: uint32 + maxDescriptorSetUpdateAfterBindAccelerationStructures*: uint32 + minAccelerationStructureScratchOffsetAlignment*: uint32 + VkPhysicalDeviceRayTracingPipelinePropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + shaderGroupHandleSize*: uint32 + maxRayRecursionDepth*: uint32 + maxShaderGroupStride*: uint32 + shaderGroupBaseAlignment*: uint32 + shaderGroupHandleCaptureReplaySize*: uint32 + maxRayDispatchInvocationCount*: uint32 + shaderGroupHandleAlignment*: uint32 + maxRayHitAttributeSize*: uint32 + VkPhysicalDeviceRayTracingPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + shaderGroupHandleSize*: uint32 + maxRecursionDepth*: uint32 + maxShaderGroupStride*: uint32 + shaderGroupBaseAlignment*: uint32 + maxGeometryCount*: uint64 + maxInstanceCount*: uint64 + maxTriangleCount*: uint64 + maxDescriptorSetAccelerationStructures*: uint32 + VkStridedDeviceAddressRegionKHR* = object + deviceAddress*: VkDeviceAddress + stride*: VkDeviceSize + size*: VkDeviceSize + VkTraceRaysIndirectCommandKHR* = object + width*: uint32 + height*: uint32 + depth*: uint32 + VkTraceRaysIndirectCommand2KHR* = object + raygenShaderRecordAddress*: VkDeviceAddress + raygenShaderRecordSize*: VkDeviceSize + missShaderBindingTableAddress*: VkDeviceAddress + missShaderBindingTableSize*: VkDeviceSize + missShaderBindingTableStride*: VkDeviceSize + hitShaderBindingTableAddress*: VkDeviceAddress + hitShaderBindingTableSize*: VkDeviceSize + hitShaderBindingTableStride*: VkDeviceSize + callableShaderBindingTableAddress*: VkDeviceAddress + callableShaderBindingTableSize*: VkDeviceSize + callableShaderBindingTableStride*: VkDeviceSize + width*: uint32 + height*: uint32 + depth*: uint32 + VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + rayTracingMaintenance1*: VkBool32 + rayTracingPipelineTraceRaysIndirect2*: VkBool32 + VkDrmFormatModifierPropertiesListEXT* = object + sType*: VkStructureType + pNext*: pointer + drmFormatModifierCount*: uint32 + pDrmFormatModifierProperties*: ptr VkDrmFormatModifierPropertiesEXT + VkDrmFormatModifierPropertiesEXT* = object + drmFormatModifier*: uint64 + drmFormatModifierPlaneCount*: uint32 + drmFormatModifierTilingFeatures*: VkFormatFeatureFlags + VkPhysicalDeviceImageDrmFormatModifierInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + drmFormatModifier*: uint64 + sharingMode*: VkSharingMode + queueFamilyIndexCount*: uint32 + pQueueFamilyIndices*: ptr uint32 + VkImageDrmFormatModifierListCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + drmFormatModifierCount*: uint32 + pDrmFormatModifiers*: ptr uint64 + VkImageDrmFormatModifierExplicitCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + drmFormatModifier*: uint64 + drmFormatModifierPlaneCount*: uint32 + pPlaneLayouts*: ptr VkSubresourceLayout + VkImageDrmFormatModifierPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + drmFormatModifier*: uint64 + VkImageStencilUsageCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + stencilUsage*: VkImageUsageFlags + VkImageStencilUsageCreateInfoEXT* = object + VkDeviceMemoryOverallocationCreateInfoAMD* = object + sType*: VkStructureType + pNext*: pointer + overallocationBehavior*: VkMemoryOverallocationBehaviorAMD + VkPhysicalDeviceFragmentDensityMapFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + fragmentDensityMap*: VkBool32 + fragmentDensityMapDynamic*: VkBool32 + fragmentDensityMapNonSubsampledImages*: VkBool32 + VkPhysicalDeviceFragmentDensityMap2FeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + fragmentDensityMapDeferred*: VkBool32 + VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM* = object + sType*: VkStructureType + pNext*: pointer + fragmentDensityMapOffset*: VkBool32 + VkPhysicalDeviceFragmentDensityMapPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + minFragmentDensityTexelSize*: VkExtent2D + maxFragmentDensityTexelSize*: VkExtent2D + fragmentDensityInvocations*: VkBool32 + VkPhysicalDeviceFragmentDensityMap2PropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + subsampledLoads*: VkBool32 + subsampledCoarseReconstructionEarlyAccess*: VkBool32 + maxSubsampledArrayLayers*: uint32 + maxDescriptorSetSubsampledSamplers*: uint32 + VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM* = object + sType*: VkStructureType + pNext*: pointer + fragmentDensityOffsetGranularity*: VkExtent2D + VkRenderPassFragmentDensityMapCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + fragmentDensityMapAttachment*: VkAttachmentReference + VkSubpassFragmentDensityMapOffsetEndInfoQCOM* = object + sType*: VkStructureType + pNext*: pointer + fragmentDensityOffsetCount*: uint32 + pFragmentDensityOffsets*: ptr VkOffset2D + VkPhysicalDeviceScalarBlockLayoutFeatures* = object + sType*: VkStructureType + pNext*: pointer + scalarBlockLayout*: VkBool32 + VkPhysicalDeviceScalarBlockLayoutFeaturesEXT* = object + VkSurfaceProtectedCapabilitiesKHR* = object + sType*: VkStructureType + pNext*: pointer + supportsProtected*: VkBool32 + VkPhysicalDeviceUniformBufferStandardLayoutFeatures* = object + sType*: VkStructureType + pNext*: pointer + uniformBufferStandardLayout*: VkBool32 + VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR* = object + VkPhysicalDeviceDepthClipEnableFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + depthClipEnable*: VkBool32 + VkPipelineRasterizationDepthClipStateCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineRasterizationDepthClipStateCreateFlagsEXT + depthClipEnable*: VkBool32 + VkPhysicalDeviceMemoryBudgetPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + heapBudget*: array[VK_MAX_MEMORY_HEAPS, VkDeviceSize] + heapUsage*: array[VK_MAX_MEMORY_HEAPS, VkDeviceSize] + VkPhysicalDeviceMemoryPriorityFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + memoryPriority*: VkBool32 + VkMemoryPriorityAllocateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + priority*: float32 + VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + pageableDeviceLocalMemory*: VkBool32 + VkPhysicalDeviceBufferDeviceAddressFeatures* = object + sType*: VkStructureType + pNext*: pointer + bufferDeviceAddress*: VkBool32 + bufferDeviceAddressCaptureReplay*: VkBool32 + bufferDeviceAddressMultiDevice*: VkBool32 + VkPhysicalDeviceBufferDeviceAddressFeaturesKHR* = object + VkPhysicalDeviceBufferDeviceAddressFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + bufferDeviceAddress*: VkBool32 + bufferDeviceAddressCaptureReplay*: VkBool32 + bufferDeviceAddressMultiDevice*: VkBool32 + VkPhysicalDeviceBufferAddressFeaturesEXT* = object + VkBufferDeviceAddressInfo* = object + sType*: VkStructureType + pNext*: pointer + buffer*: VkBuffer + VkBufferDeviceAddressInfoKHR* = object + VkBufferDeviceAddressInfoEXT* = object + VkBufferOpaqueCaptureAddressCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + opaqueCaptureAddress*: uint64 + VkBufferOpaqueCaptureAddressCreateInfoKHR* = object + VkBufferDeviceAddressCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + deviceAddress*: VkDeviceAddress + VkPhysicalDeviceImageViewImageFormatInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + imageViewType*: VkImageViewType + VkFilterCubicImageViewImageFormatPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + filterCubic*: VkBool32 + filterCubicMinmax*: VkBool32 + VkPhysicalDeviceImagelessFramebufferFeatures* = object + sType*: VkStructureType + pNext*: pointer + imagelessFramebuffer*: VkBool32 + VkPhysicalDeviceImagelessFramebufferFeaturesKHR* = object + VkFramebufferAttachmentsCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + attachmentImageInfoCount*: uint32 + pAttachmentImageInfos*: ptr VkFramebufferAttachmentImageInfo + VkFramebufferAttachmentsCreateInfoKHR* = object + VkFramebufferAttachmentImageInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkImageCreateFlags + usage*: VkImageUsageFlags + width*: uint32 + height*: uint32 + layerCount*: uint32 + viewFormatCount*: uint32 + pViewFormats*: ptr VkFormat + VkFramebufferAttachmentImageInfoKHR* = object + VkRenderPassAttachmentBeginInfo* = object + sType*: VkStructureType + pNext*: pointer + attachmentCount*: uint32 + pAttachments*: ptr VkImageView + VkRenderPassAttachmentBeginInfoKHR* = object + VkPhysicalDeviceTextureCompressionASTCHDRFeatures* = object + sType*: VkStructureType + pNext*: pointer + textureCompressionASTC_HDR*: VkBool32 + VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT* = object + VkPhysicalDeviceCooperativeMatrixFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + cooperativeMatrix*: VkBool32 + cooperativeMatrixRobustBufferAccess*: VkBool32 + VkPhysicalDeviceCooperativeMatrixPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + cooperativeMatrixSupportedStages*: VkShaderStageFlags + VkCooperativeMatrixPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + MSize*: uint32 + NSize*: uint32 + KSize*: uint32 + AType*: VkComponentTypeNV + BType*: VkComponentTypeNV + CType*: VkComponentTypeNV + DType*: VkComponentTypeNV + scope*: VkScopeNV + VkPhysicalDeviceYcbcrImageArraysFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + ycbcrImageArrays*: VkBool32 + VkImageViewHandleInfoNVX* = object + sType*: VkStructureType + pNext*: pointer + imageView*: VkImageView + descriptorType*: VkDescriptorType + sampler*: VkSampler + VkImageViewAddressPropertiesNVX* = object + sType*: VkStructureType + pNext*: pointer + deviceAddress*: VkDeviceAddress + size*: VkDeviceSize + VkPipelineCreationFeedback* = object + flags*: VkPipelineCreationFeedbackFlags + duration*: uint64 + VkPipelineCreationFeedbackEXT* = object + VkPipelineCreationFeedbackCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + pPipelineCreationFeedback*: ptr VkPipelineCreationFeedback + pipelineStageCreationFeedbackCount*: uint32 + pPipelineStageCreationFeedbacks*: ptr VkPipelineCreationFeedback + VkPipelineCreationFeedbackCreateInfoEXT* = object + VkPhysicalDevicePresentBarrierFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + presentBarrier*: VkBool32 + VkSurfaceCapabilitiesPresentBarrierNV* = object + sType*: VkStructureType + pNext*: pointer + presentBarrierSupported*: VkBool32 + VkSwapchainPresentBarrierCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + presentBarrierEnable*: VkBool32 + VkPhysicalDevicePerformanceQueryFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + performanceCounterQueryPools*: VkBool32 + performanceCounterMultipleQueryPools*: VkBool32 + VkPhysicalDevicePerformanceQueryPropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + allowCommandBufferQueryCopies*: VkBool32 + VkPerformanceCounterKHR* = object + sType*: VkStructureType + pNext*: pointer + unit*: VkPerformanceCounterUnitKHR + scope*: VkPerformanceCounterScopeKHR + storage*: VkPerformanceCounterStorageKHR + uuid*: array[VK_UUID_SIZE, uint8] + VkPerformanceCounterDescriptionKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPerformanceCounterDescriptionFlagsKHR + name*: array[VK_MAX_DESCRIPTION_SIZE, char] + category*: array[VK_MAX_DESCRIPTION_SIZE, char] + description*: array[VK_MAX_DESCRIPTION_SIZE, char] + VkQueryPoolPerformanceCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + queueFamilyIndex*: uint32 + counterIndexCount*: uint32 + pCounterIndices*: ptr uint32 + VkPerformanceCounterResultKHR* {.union.} = object + int32*: int32 + int64*: int64 + uint32*: uint32 + uint64*: uint64 + float32*: float32 + float64*: float64 + VkAcquireProfilingLockInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkAcquireProfilingLockFlagsKHR + timeout*: uint64 + VkPerformanceQuerySubmitInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + counterPassIndex*: uint32 + VkPerformanceQueryReservationInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + maxPerformanceQueriesPerPool*: uint32 + VkHeadlessSurfaceCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkHeadlessSurfaceCreateFlagsEXT + VkPhysicalDeviceCoverageReductionModeFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + coverageReductionMode*: VkBool32 + VkPipelineCoverageReductionStateCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkPipelineCoverageReductionStateCreateFlagsNV + coverageReductionMode*: VkCoverageReductionModeNV + VkFramebufferMixedSamplesCombinationNV* = object + sType*: VkStructureType + pNext*: pointer + coverageReductionMode*: VkCoverageReductionModeNV + rasterizationSamples*: VkSampleCountFlagBits + depthStencilSamples*: VkSampleCountFlags + colorSamples*: VkSampleCountFlags + VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL* = object + sType*: VkStructureType + pNext*: pointer + shaderIntegerFunctions2*: VkBool32 + VkPerformanceValueDataINTEL* {.union.} = object + value32*: uint32 + value64*: uint64 + valueFloat*: float32 + valueBool*: VkBool32 + valueString*: cstring + VkPerformanceValueINTEL* = object + thetype*: VkPerformanceValueTypeINTEL + data*: VkPerformanceValueDataINTEL + VkInitializePerformanceApiInfoINTEL* = object + sType*: VkStructureType + pNext*: pointer + pUserData*: pointer + VkQueryPoolPerformanceQueryCreateInfoINTEL* = object + sType*: VkStructureType + pNext*: pointer + performanceCountersSampling*: VkQueryPoolSamplingModeINTEL + VkQueryPoolCreateInfoINTEL* = object + VkPerformanceMarkerInfoINTEL* = object + sType*: VkStructureType + pNext*: pointer + marker*: uint64 + VkPerformanceStreamMarkerInfoINTEL* = object + sType*: VkStructureType + pNext*: pointer + marker*: uint32 + VkPerformanceOverrideInfoINTEL* = object + sType*: VkStructureType + pNext*: pointer + thetype*: VkPerformanceOverrideTypeINTEL + enable*: VkBool32 + parameter*: uint64 + VkPerformanceConfigurationAcquireInfoINTEL* = object + sType*: VkStructureType + pNext*: pointer + thetype*: VkPerformanceConfigurationTypeINTEL + VkPhysicalDeviceShaderClockFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + shaderSubgroupClock*: VkBool32 + shaderDeviceClock*: VkBool32 + VkPhysicalDeviceIndexTypeUint8FeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + indexTypeUint8*: VkBool32 + VkPhysicalDeviceShaderSMBuiltinsPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + shaderSMCount*: uint32 + shaderWarpsPerSM*: uint32 + VkPhysicalDeviceShaderSMBuiltinsFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + shaderSMBuiltins*: VkBool32 + VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + fragmentShaderSampleInterlock*: VkBool32 + fragmentShaderPixelInterlock*: VkBool32 + fragmentShaderShadingRateInterlock*: VkBool32 + VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures* = object + sType*: VkStructureType + pNext*: pointer + separateDepthStencilLayouts*: VkBool32 + VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR* = object + VkAttachmentReferenceStencilLayout* = object + sType*: VkStructureType + pNext*: pointer + stencilLayout*: VkImageLayout + VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + primitiveTopologyListRestart*: VkBool32 + primitiveTopologyPatchListRestart*: VkBool32 + VkAttachmentReferenceStencilLayoutKHR* = object + VkAttachmentDescriptionStencilLayout* = object + sType*: VkStructureType + pNext*: pointer + stencilInitialLayout*: VkImageLayout + stencilFinalLayout*: VkImageLayout + VkAttachmentDescriptionStencilLayoutKHR* = object + VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + pipelineExecutableInfo*: VkBool32 + VkPipelineInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pipeline*: VkPipeline + VkPipelineInfoEXT* = object + VkPipelineExecutablePropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + stages*: VkShaderStageFlags + name*: array[VK_MAX_DESCRIPTION_SIZE, char] + description*: array[VK_MAX_DESCRIPTION_SIZE, char] + subgroupSize*: uint32 + VkPipelineExecutableInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pipeline*: VkPipeline + executableIndex*: uint32 + VkPipelineExecutableStatisticValueKHR* {.union.} = object + b32*: VkBool32 + i64*: int64 + u64*: uint64 + f64*: float64 + VkPipelineExecutableStatisticKHR* = object + sType*: VkStructureType + pNext*: pointer + name*: array[VK_MAX_DESCRIPTION_SIZE, char] + description*: array[VK_MAX_DESCRIPTION_SIZE, char] + format*: VkPipelineExecutableStatisticFormatKHR + value*: VkPipelineExecutableStatisticValueKHR + VkPipelineExecutableInternalRepresentationKHR* = object + sType*: VkStructureType + pNext*: pointer + name*: array[VK_MAX_DESCRIPTION_SIZE, char] + description*: array[VK_MAX_DESCRIPTION_SIZE, char] + isText*: VkBool32 + dataSize*: csize_t + pData*: pointer + VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures* = object + sType*: VkStructureType + pNext*: pointer + shaderDemoteToHelperInvocation*: VkBool32 + VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT* = object + VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + texelBufferAlignment*: VkBool32 + VkPhysicalDeviceTexelBufferAlignmentProperties* = object + sType*: VkStructureType + pNext*: pointer + storageTexelBufferOffsetAlignmentBytes*: VkDeviceSize + storageTexelBufferOffsetSingleTexelAlignment*: VkBool32 + uniformTexelBufferOffsetAlignmentBytes*: VkDeviceSize + uniformTexelBufferOffsetSingleTexelAlignment*: VkBool32 + VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT* = object + VkPhysicalDeviceSubgroupSizeControlFeatures* = object + sType*: VkStructureType + pNext*: pointer + subgroupSizeControl*: VkBool32 + computeFullSubgroups*: VkBool32 + VkPhysicalDeviceSubgroupSizeControlFeaturesEXT* = object + VkPhysicalDeviceSubgroupSizeControlProperties* = object + sType*: VkStructureType + pNext*: pointer + minSubgroupSize*: uint32 + maxSubgroupSize*: uint32 + maxComputeWorkgroupSubgroups*: uint32 + requiredSubgroupSizeStages*: VkShaderStageFlags + VkPhysicalDeviceSubgroupSizeControlPropertiesEXT* = object + VkPipelineShaderStageRequiredSubgroupSizeCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + requiredSubgroupSize*: uint32 + VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT* = object + VkSubpassShadingPipelineCreateInfoHUAWEI* = object + sType*: VkStructureType + pNext*: pointer + renderPass*: VkRenderPass + subpass*: uint32 + VkPhysicalDeviceSubpassShadingPropertiesHUAWEI* = object + sType*: VkStructureType + pNext*: pointer + maxSubpassShadingWorkgroupSizeAspectRatio*: uint32 + VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI* = object + sType*: VkStructureType + pNext*: pointer + maxWorkGroupCount*: array[3, uint32] + maxWorkGroupSize*: array[3, uint32] + maxOutputClusterCount*: uint32 + VkMemoryOpaqueCaptureAddressAllocateInfo* = object + sType*: VkStructureType + pNext*: pointer + opaqueCaptureAddress*: uint64 + VkMemoryOpaqueCaptureAddressAllocateInfoKHR* = object + VkDeviceMemoryOpaqueCaptureAddressInfo* = object + sType*: VkStructureType + pNext*: pointer + memory*: VkDeviceMemory + VkDeviceMemoryOpaqueCaptureAddressInfoKHR* = object + VkPhysicalDeviceLineRasterizationFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + rectangularLines*: VkBool32 + bresenhamLines*: VkBool32 + smoothLines*: VkBool32 + stippledRectangularLines*: VkBool32 + stippledBresenhamLines*: VkBool32 + stippledSmoothLines*: VkBool32 + VkPhysicalDeviceLineRasterizationPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + lineSubPixelPrecisionBits*: uint32 + VkPipelineRasterizationLineStateCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + lineRasterizationMode*: VkLineRasterizationModeEXT + stippledLineEnable*: VkBool32 + lineStippleFactor*: uint32 + lineStipplePattern*: uint16 + VkPhysicalDevicePipelineCreationCacheControlFeatures* = object + sType*: VkStructureType + pNext*: pointer + pipelineCreationCacheControl*: VkBool32 + VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT* = object + VkPhysicalDeviceVulkan11Features* = object + sType*: VkStructureType + pNext*: pointer + storageBuffer16BitAccess*: VkBool32 + uniformAndStorageBuffer16BitAccess*: VkBool32 + storagePushConstant16*: VkBool32 + storageInputOutput16*: VkBool32 + multiview*: VkBool32 + multiviewGeometryShader*: VkBool32 + multiviewTessellationShader*: VkBool32 + variablePointersStorageBuffer*: VkBool32 + variablePointers*: VkBool32 + protectedMemory*: VkBool32 + samplerYcbcrConversion*: VkBool32 + shaderDrawParameters*: VkBool32 + VkPhysicalDeviceVulkan11Properties* = object + sType*: VkStructureType + pNext*: pointer + deviceUUID*: array[VK_UUID_SIZE, uint8] + driverUUID*: array[VK_UUID_SIZE, uint8] + deviceLUID*: array[VK_LUID_SIZE, uint8] + deviceNodeMask*: uint32 + deviceLUIDValid*: VkBool32 + subgroupSize*: uint32 + subgroupSupportedStages*: VkShaderStageFlags + subgroupSupportedOperations*: VkSubgroupFeatureFlags + subgroupQuadOperationsInAllStages*: VkBool32 + pointClippingBehavior*: VkPointClippingBehavior + maxMultiviewViewCount*: uint32 + maxMultiviewInstanceIndex*: uint32 + protectedNoFault*: VkBool32 + maxPerSetDescriptors*: uint32 + maxMemoryAllocationSize*: VkDeviceSize + VkPhysicalDeviceVulkan12Features* = object + sType*: VkStructureType + pNext*: pointer + samplerMirrorClampToEdge*: VkBool32 + drawIndirectCount*: VkBool32 + storageBuffer8BitAccess*: VkBool32 + uniformAndStorageBuffer8BitAccess*: VkBool32 + storagePushConstant8*: VkBool32 + shaderBufferInt64Atomics*: VkBool32 + shaderSharedInt64Atomics*: VkBool32 + shaderFloat16*: VkBool32 + shaderInt8*: VkBool32 + descriptorIndexing*: VkBool32 + shaderInputAttachmentArrayDynamicIndexing*: VkBool32 + shaderUniformTexelBufferArrayDynamicIndexing*: VkBool32 + shaderStorageTexelBufferArrayDynamicIndexing*: VkBool32 + shaderUniformBufferArrayNonUniformIndexing*: VkBool32 + shaderSampledImageArrayNonUniformIndexing*: VkBool32 + shaderStorageBufferArrayNonUniformIndexing*: VkBool32 + shaderStorageImageArrayNonUniformIndexing*: VkBool32 + shaderInputAttachmentArrayNonUniformIndexing*: VkBool32 + shaderUniformTexelBufferArrayNonUniformIndexing*: VkBool32 + shaderStorageTexelBufferArrayNonUniformIndexing*: VkBool32 + descriptorBindingUniformBufferUpdateAfterBind*: VkBool32 + descriptorBindingSampledImageUpdateAfterBind*: VkBool32 + descriptorBindingStorageImageUpdateAfterBind*: VkBool32 + descriptorBindingStorageBufferUpdateAfterBind*: VkBool32 + descriptorBindingUniformTexelBufferUpdateAfterBind*: VkBool32 + descriptorBindingStorageTexelBufferUpdateAfterBind*: VkBool32 + descriptorBindingUpdateUnusedWhilePending*: VkBool32 + descriptorBindingPartiallyBound*: VkBool32 + descriptorBindingVariableDescriptorCount*: VkBool32 + runtimeDescriptorArray*: VkBool32 + samplerFilterMinmax*: VkBool32 + scalarBlockLayout*: VkBool32 + imagelessFramebuffer*: VkBool32 + uniformBufferStandardLayout*: VkBool32 + shaderSubgroupExtendedTypes*: VkBool32 + separateDepthStencilLayouts*: VkBool32 + hostQueryReset*: VkBool32 + timelineSemaphore*: VkBool32 + bufferDeviceAddress*: VkBool32 + bufferDeviceAddressCaptureReplay*: VkBool32 + bufferDeviceAddressMultiDevice*: VkBool32 + vulkanMemoryModel*: VkBool32 + vulkanMemoryModelDeviceScope*: VkBool32 + vulkanMemoryModelAvailabilityVisibilityChains*: VkBool32 + shaderOutputViewportIndex*: VkBool32 + shaderOutputLayer*: VkBool32 + subgroupBroadcastDynamicId*: VkBool32 + VkPhysicalDeviceVulkan12Properties* = object + sType*: VkStructureType + pNext*: pointer + driverID*: VkDriverId + driverName*: array[VK_MAX_DRIVER_NAME_SIZE, char] + driverInfo*: array[VK_MAX_DRIVER_INFO_SIZE, char] + conformanceVersion*: VkConformanceVersion + denormBehaviorIndependence*: VkShaderFloatControlsIndependence + roundingModeIndependence*: VkShaderFloatControlsIndependence + shaderSignedZeroInfNanPreserveFloat16*: VkBool32 + shaderSignedZeroInfNanPreserveFloat32*: VkBool32 + shaderSignedZeroInfNanPreserveFloat64*: VkBool32 + shaderDenormPreserveFloat16*: VkBool32 + shaderDenormPreserveFloat32*: VkBool32 + shaderDenormPreserveFloat64*: VkBool32 + shaderDenormFlushToZeroFloat16*: VkBool32 + shaderDenormFlushToZeroFloat32*: VkBool32 + shaderDenormFlushToZeroFloat64*: VkBool32 + shaderRoundingModeRTEFloat16*: VkBool32 + shaderRoundingModeRTEFloat32*: VkBool32 + shaderRoundingModeRTEFloat64*: VkBool32 + shaderRoundingModeRTZFloat16*: VkBool32 + shaderRoundingModeRTZFloat32*: VkBool32 + shaderRoundingModeRTZFloat64*: VkBool32 + maxUpdateAfterBindDescriptorsInAllPools*: uint32 + shaderUniformBufferArrayNonUniformIndexingNative*: VkBool32 + shaderSampledImageArrayNonUniformIndexingNative*: VkBool32 + shaderStorageBufferArrayNonUniformIndexingNative*: VkBool32 + shaderStorageImageArrayNonUniformIndexingNative*: VkBool32 + shaderInputAttachmentArrayNonUniformIndexingNative*: VkBool32 + robustBufferAccessUpdateAfterBind*: VkBool32 + quadDivergentImplicitLod*: VkBool32 + maxPerStageDescriptorUpdateAfterBindSamplers*: uint32 + maxPerStageDescriptorUpdateAfterBindUniformBuffers*: uint32 + maxPerStageDescriptorUpdateAfterBindStorageBuffers*: uint32 + maxPerStageDescriptorUpdateAfterBindSampledImages*: uint32 + maxPerStageDescriptorUpdateAfterBindStorageImages*: uint32 + maxPerStageDescriptorUpdateAfterBindInputAttachments*: uint32 + maxPerStageUpdateAfterBindResources*: uint32 + maxDescriptorSetUpdateAfterBindSamplers*: uint32 + maxDescriptorSetUpdateAfterBindUniformBuffers*: uint32 + maxDescriptorSetUpdateAfterBindUniformBuffersDynamic*: uint32 + maxDescriptorSetUpdateAfterBindStorageBuffers*: uint32 + maxDescriptorSetUpdateAfterBindStorageBuffersDynamic*: uint32 + maxDescriptorSetUpdateAfterBindSampledImages*: uint32 + maxDescriptorSetUpdateAfterBindStorageImages*: uint32 + maxDescriptorSetUpdateAfterBindInputAttachments*: uint32 + supportedDepthResolveModes*: VkResolveModeFlags + supportedStencilResolveModes*: VkResolveModeFlags + independentResolveNone*: VkBool32 + independentResolve*: VkBool32 + filterMinmaxSingleComponentFormats*: VkBool32 + filterMinmaxImageComponentMapping*: VkBool32 + maxTimelineSemaphoreValueDifference*: uint64 + framebufferIntegerColorSampleCounts*: VkSampleCountFlags + VkPhysicalDeviceVulkan13Features* = object + sType*: VkStructureType + pNext*: pointer + robustImageAccess*: VkBool32 + inlineUniformBlock*: VkBool32 + descriptorBindingInlineUniformBlockUpdateAfterBind*: VkBool32 + pipelineCreationCacheControl*: VkBool32 + privateData*: VkBool32 + shaderDemoteToHelperInvocation*: VkBool32 + shaderTerminateInvocation*: VkBool32 + subgroupSizeControl*: VkBool32 + computeFullSubgroups*: VkBool32 + synchronization2*: VkBool32 + textureCompressionASTC_HDR*: VkBool32 + shaderZeroInitializeWorkgroupMemory*: VkBool32 + dynamicRendering*: VkBool32 + shaderIntegerDotProduct*: VkBool32 + maintenance4*: VkBool32 + VkPhysicalDeviceVulkan13Properties* = object + sType*: VkStructureType + pNext*: pointer + minSubgroupSize*: uint32 + maxSubgroupSize*: uint32 + maxComputeWorkgroupSubgroups*: uint32 + requiredSubgroupSizeStages*: VkShaderStageFlags + maxInlineUniformBlockSize*: uint32 + maxPerStageDescriptorInlineUniformBlocks*: uint32 + maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks*: uint32 + maxDescriptorSetInlineUniformBlocks*: uint32 + maxDescriptorSetUpdateAfterBindInlineUniformBlocks*: uint32 + maxInlineUniformTotalSize*: uint32 + integerDotProduct8BitUnsignedAccelerated*: VkBool32 + integerDotProduct8BitSignedAccelerated*: VkBool32 + integerDotProduct8BitMixedSignednessAccelerated*: VkBool32 + integerDotProduct4x8BitPackedUnsignedAccelerated*: VkBool32 + integerDotProduct4x8BitPackedSignedAccelerated*: VkBool32 + integerDotProduct4x8BitPackedMixedSignednessAccelerated*: VkBool32 + integerDotProduct16BitUnsignedAccelerated*: VkBool32 + integerDotProduct16BitSignedAccelerated*: VkBool32 + integerDotProduct16BitMixedSignednessAccelerated*: VkBool32 + integerDotProduct32BitUnsignedAccelerated*: VkBool32 + integerDotProduct32BitSignedAccelerated*: VkBool32 + integerDotProduct32BitMixedSignednessAccelerated*: VkBool32 + integerDotProduct64BitUnsignedAccelerated*: VkBool32 + integerDotProduct64BitSignedAccelerated*: VkBool32 + integerDotProduct64BitMixedSignednessAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating8BitUnsignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating8BitSignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating16BitUnsignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating16BitSignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating32BitUnsignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating32BitSignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating64BitUnsignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating64BitSignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated*: VkBool32 + storageTexelBufferOffsetAlignmentBytes*: VkDeviceSize + storageTexelBufferOffsetSingleTexelAlignment*: VkBool32 + uniformTexelBufferOffsetAlignmentBytes*: VkDeviceSize + uniformTexelBufferOffsetSingleTexelAlignment*: VkBool32 + maxBufferSize*: VkDeviceSize + VkPipelineCompilerControlCreateInfoAMD* = object + sType*: VkStructureType + pNext*: pointer + compilerControlFlags*: VkPipelineCompilerControlFlagsAMD + VkPhysicalDeviceCoherentMemoryFeaturesAMD* = object + sType*: VkStructureType + pNext*: pointer + deviceCoherentMemory*: VkBool32 + VkFaultData* = object + sType*: VkStructureType + pNext*: pointer + faultLevel*: VkFaultLevel + faultType*: VkFaultType + VkFaultCallbackInfo* = object + sType*: VkStructureType + pNext*: pointer + faultCount*: uint32 + pFaults*: ptr VkFaultData + pfnFaultCallback*: PFN_vkFaultCallbackFunction + VkPhysicalDeviceToolProperties* = object + sType*: VkStructureType + pNext*: pointer + name*: array[VK_MAX_EXTENSION_NAME_SIZE, char] + version*: array[VK_MAX_EXTENSION_NAME_SIZE, char] + purposes*: VkToolPurposeFlags + description*: array[VK_MAX_DESCRIPTION_SIZE, char] + layer*: array[VK_MAX_EXTENSION_NAME_SIZE, char] + VkPhysicalDeviceToolPropertiesEXT* = object + VkSamplerCustomBorderColorCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + customBorderColor*: VkClearColorValue + format*: VkFormat + VkPhysicalDeviceCustomBorderColorPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + maxCustomBorderColorSamplers*: uint32 + VkPhysicalDeviceCustomBorderColorFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + customBorderColors*: VkBool32 + customBorderColorWithoutFormat*: VkBool32 + VkSamplerBorderColorComponentMappingCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + components*: VkComponentMapping + srgb*: VkBool32 + VkPhysicalDeviceBorderColorSwizzleFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + borderColorSwizzle*: VkBool32 + borderColorSwizzleFromImage*: VkBool32 + VkDeviceOrHostAddressKHR* {.union.} = object + deviceAddress*: VkDeviceAddress + hostAddress*: pointer + VkDeviceOrHostAddressConstKHR* {.union.} = object + deviceAddress*: VkDeviceAddress + hostAddress*: pointer + VkAccelerationStructureGeometryTrianglesDataKHR* = object + sType*: VkStructureType + pNext*: pointer + vertexFormat*: VkFormat + vertexData*: VkDeviceOrHostAddressConstKHR + vertexStride*: VkDeviceSize + maxVertex*: uint32 + indexType*: VkIndexType + indexData*: VkDeviceOrHostAddressConstKHR + transformData*: VkDeviceOrHostAddressConstKHR + VkAccelerationStructureGeometryAabbsDataKHR* = object + sType*: VkStructureType + pNext*: pointer + data*: VkDeviceOrHostAddressConstKHR + stride*: VkDeviceSize + VkAccelerationStructureGeometryInstancesDataKHR* = object + sType*: VkStructureType + pNext*: pointer + arrayOfPointers*: VkBool32 + data*: VkDeviceOrHostAddressConstKHR + VkAccelerationStructureGeometryDataKHR* {.union.} = object + triangles*: VkAccelerationStructureGeometryTrianglesDataKHR + aabbs*: VkAccelerationStructureGeometryAabbsDataKHR + instances*: VkAccelerationStructureGeometryInstancesDataKHR + VkAccelerationStructureGeometryKHR* = object + sType*: VkStructureType + pNext*: pointer + geometryType*: VkGeometryTypeKHR + geometry*: VkAccelerationStructureGeometryDataKHR + flags*: VkGeometryFlagsKHR + VkAccelerationStructureBuildGeometryInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + thetype*: VkAccelerationStructureTypeKHR + flags*: VkBuildAccelerationStructureFlagsKHR + mode*: VkBuildAccelerationStructureModeKHR + srcAccelerationStructure*: VkAccelerationStructureKHR + dstAccelerationStructure*: VkAccelerationStructureKHR + geometryCount*: uint32 + pGeometries*: ptr VkAccelerationStructureGeometryKHR + ppGeometries*: ptr ptr VkAccelerationStructureGeometryKHR + scratchData*: VkDeviceOrHostAddressKHR + VkAccelerationStructureBuildRangeInfoKHR* = object + primitiveCount*: uint32 + primitiveOffset*: uint32 + firstVertex*: uint32 + transformOffset*: uint32 + VkAccelerationStructureCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + createFlags*: VkAccelerationStructureCreateFlagsKHR + buffer*: VkBuffer + offset*: VkDeviceSize + size*: VkDeviceSize + thetype*: VkAccelerationStructureTypeKHR + deviceAddress*: VkDeviceAddress + VkAabbPositionsKHR* = object + minX*: float32 + minY*: float32 + minZ*: float32 + maxX*: float32 + maxY*: float32 + maxZ*: float32 + VkAabbPositionsNV* = object + VkTransformMatrixKHR* = object + matrix*: array[3*4, float32] + VkTransformMatrixNV* = object + VkAccelerationStructureInstanceKHR* = object + transform*: VkTransformMatrixKHR + instanceCustomIndex*: uint32 + mask*: uint32 + instanceShaderBindingTableRecordOffset*: uint32 + flags*: VkGeometryInstanceFlagsKHR + accelerationStructureReference*: uint64 + VkAccelerationStructureInstanceNV* = object + VkAccelerationStructureDeviceAddressInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + accelerationStructure*: VkAccelerationStructureKHR + VkAccelerationStructureVersionInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pVersionData*: ptr uint8 + VkCopyAccelerationStructureInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + src*: VkAccelerationStructureKHR + dst*: VkAccelerationStructureKHR + mode*: VkCopyAccelerationStructureModeKHR + VkCopyAccelerationStructureToMemoryInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + src*: VkAccelerationStructureKHR + dst*: VkDeviceOrHostAddressKHR + mode*: VkCopyAccelerationStructureModeKHR + VkCopyMemoryToAccelerationStructureInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + src*: VkDeviceOrHostAddressConstKHR + dst*: VkAccelerationStructureKHR + mode*: VkCopyAccelerationStructureModeKHR + VkRayTracingPipelineInterfaceCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + maxPipelineRayPayloadSize*: uint32 + maxPipelineRayHitAttributeSize*: uint32 + VkPipelineLibraryCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + libraryCount*: uint32 + pLibraries*: ptr VkPipeline + VkRefreshObjectKHR* = object + objectType*: VkObjectType + objectHandle*: uint64 + flags*: VkRefreshObjectFlagsKHR + VkRefreshObjectListKHR* = object + sType*: VkStructureType + pNext*: pointer + objectCount*: uint32 + pObjects*: ptr VkRefreshObjectKHR + VkPhysicalDeviceExtendedDynamicStateFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + extendedDynamicState*: VkBool32 + VkPhysicalDeviceExtendedDynamicState2FeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + extendedDynamicState2*: VkBool32 + extendedDynamicState2LogicOp*: VkBool32 + extendedDynamicState2PatchControlPoints*: VkBool32 + VkPhysicalDeviceExtendedDynamicState3FeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + extendedDynamicState3TessellationDomainOrigin*: VkBool32 + extendedDynamicState3DepthClampEnable*: VkBool32 + extendedDynamicState3PolygonMode*: VkBool32 + extendedDynamicState3RasterizationSamples*: VkBool32 + extendedDynamicState3SampleMask*: VkBool32 + extendedDynamicState3AlphaToCoverageEnable*: VkBool32 + extendedDynamicState3AlphaToOneEnable*: VkBool32 + extendedDynamicState3LogicOpEnable*: VkBool32 + extendedDynamicState3ColorBlendEnable*: VkBool32 + extendedDynamicState3ColorBlendEquation*: VkBool32 + extendedDynamicState3ColorWriteMask*: VkBool32 + extendedDynamicState3RasterizationStream*: VkBool32 + extendedDynamicState3ConservativeRasterizationMode*: VkBool32 + extendedDynamicState3ExtraPrimitiveOverestimationSize*: VkBool32 + extendedDynamicState3DepthClipEnable*: VkBool32 + extendedDynamicState3SampleLocationsEnable*: VkBool32 + extendedDynamicState3ColorBlendAdvanced*: VkBool32 + extendedDynamicState3ProvokingVertexMode*: VkBool32 + extendedDynamicState3LineRasterizationMode*: VkBool32 + extendedDynamicState3LineStippleEnable*: VkBool32 + extendedDynamicState3DepthClipNegativeOneToOne*: VkBool32 + extendedDynamicState3ViewportWScalingEnable*: VkBool32 + extendedDynamicState3ViewportSwizzle*: VkBool32 + extendedDynamicState3CoverageToColorEnable*: VkBool32 + extendedDynamicState3CoverageToColorLocation*: VkBool32 + extendedDynamicState3CoverageModulationMode*: VkBool32 + extendedDynamicState3CoverageModulationTableEnable*: VkBool32 + extendedDynamicState3CoverageModulationTable*: VkBool32 + extendedDynamicState3CoverageReductionMode*: VkBool32 + extendedDynamicState3RepresentativeFragmentTestEnable*: VkBool32 + extendedDynamicState3ShadingRateImageEnable*: VkBool32 + VkPhysicalDeviceExtendedDynamicState3PropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + dynamicPrimitiveTopologyUnrestricted*: VkBool32 + VkColorBlendEquationEXT* = object + srcColorBlendFactor*: VkBlendFactor + dstColorBlendFactor*: VkBlendFactor + colorBlendOp*: VkBlendOp + srcAlphaBlendFactor*: VkBlendFactor + dstAlphaBlendFactor*: VkBlendFactor + alphaBlendOp*: VkBlendOp + VkColorBlendAdvancedEXT* = object + advancedBlendOp*: VkBlendOp + srcPremultiplied*: VkBool32 + dstPremultiplied*: VkBool32 + blendOverlap*: VkBlendOverlapEXT + clampResults*: VkBool32 + VkRenderPassTransformBeginInfoQCOM* = object + sType*: VkStructureType + pNext*: pointer + transform*: VkSurfaceTransformFlagBitsKHR + VkCopyCommandTransformInfoQCOM* = object + sType*: VkStructureType + pNext*: pointer + transform*: VkSurfaceTransformFlagBitsKHR + VkCommandBufferInheritanceRenderPassTransformInfoQCOM* = object + sType*: VkStructureType + pNext*: pointer + transform*: VkSurfaceTransformFlagBitsKHR + renderArea*: VkRect2D + VkPhysicalDeviceDiagnosticsConfigFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + diagnosticsConfig*: VkBool32 + VkDeviceDiagnosticsConfigCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDeviceDiagnosticsConfigFlagsNV + VkPipelineOfflineCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + pipelineIdentifier*: array[VK_UUID_SIZE, uint8] + matchControl*: VkPipelineMatchControl + poolEntrySize*: VkDeviceSize + VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures* = object + sType*: VkStructureType + pNext*: pointer + shaderZeroInitializeWorkgroupMemory*: VkBool32 + VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR* = object + VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + shaderSubgroupUniformControlFlow*: VkBool32 + VkPhysicalDeviceRobustness2FeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + robustBufferAccess2*: VkBool32 + robustImageAccess2*: VkBool32 + nullDescriptor*: VkBool32 + VkPhysicalDeviceRobustness2PropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + robustStorageBufferAccessSizeAlignment*: VkDeviceSize + robustUniformBufferAccessSizeAlignment*: VkDeviceSize + VkPhysicalDeviceImageRobustnessFeatures* = object + sType*: VkStructureType + pNext*: pointer + robustImageAccess*: VkBool32 + VkPhysicalDeviceImageRobustnessFeaturesEXT* = object + VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + workgroupMemoryExplicitLayout*: VkBool32 + workgroupMemoryExplicitLayoutScalarBlockLayout*: VkBool32 + workgroupMemoryExplicitLayout8BitAccess*: VkBool32 + workgroupMemoryExplicitLayout16BitAccess*: VkBool32 + VkPhysicalDevice4444FormatsFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + formatA4R4G4B4*: VkBool32 + formatA4B4G4R4*: VkBool32 + VkPhysicalDeviceSubpassShadingFeaturesHUAWEI* = object + sType*: VkStructureType + pNext*: pointer + subpassShading*: VkBool32 + VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI* = object + sType*: VkStructureType + pNext*: pointer + clustercullingShader*: VkBool32 + multiviewClusterCullingShader*: VkBool32 + VkBufferCopy2* = object + sType*: VkStructureType + pNext*: pointer + srcOffset*: VkDeviceSize + dstOffset*: VkDeviceSize + size*: VkDeviceSize + VkBufferCopy2KHR* = object + VkImageCopy2* = object + sType*: VkStructureType + pNext*: pointer + srcSubresource*: VkImageSubresourceLayers + srcOffset*: VkOffset3D + dstSubresource*: VkImageSubresourceLayers + dstOffset*: VkOffset3D + extent*: VkExtent3D + VkImageCopy2KHR* = object + VkImageBlit2* = object + sType*: VkStructureType + pNext*: pointer + srcSubresource*: VkImageSubresourceLayers + srcOffsets*: array[2, VkOffset3D] + dstSubresource*: VkImageSubresourceLayers + dstOffsets*: array[2, VkOffset3D] + VkImageBlit2KHR* = object + VkBufferImageCopy2* = object + sType*: VkStructureType + pNext*: pointer + bufferOffset*: VkDeviceSize + bufferRowLength*: uint32 + bufferImageHeight*: uint32 + imageSubresource*: VkImageSubresourceLayers + imageOffset*: VkOffset3D + imageExtent*: VkExtent3D + VkBufferImageCopy2KHR* = object + VkImageResolve2* = object + sType*: VkStructureType + pNext*: pointer + srcSubresource*: VkImageSubresourceLayers + srcOffset*: VkOffset3D + dstSubresource*: VkImageSubresourceLayers + dstOffset*: VkOffset3D + extent*: VkExtent3D + VkImageResolve2KHR* = object + VkCopyBufferInfo2* = object + sType*: VkStructureType + pNext*: pointer + srcBuffer*: VkBuffer + dstBuffer*: VkBuffer + regionCount*: uint32 + pRegions*: ptr VkBufferCopy2 + VkCopyBufferInfo2KHR* = object + VkCopyImageInfo2* = object + sType*: VkStructureType + pNext*: pointer + srcImage*: VkImage + srcImageLayout*: VkImageLayout + dstImage*: VkImage + dstImageLayout*: VkImageLayout + regionCount*: uint32 + pRegions*: ptr VkImageCopy2 + VkCopyImageInfo2KHR* = object + VkBlitImageInfo2* = object + sType*: VkStructureType + pNext*: pointer + srcImage*: VkImage + srcImageLayout*: VkImageLayout + dstImage*: VkImage + dstImageLayout*: VkImageLayout + regionCount*: uint32 + pRegions*: ptr VkImageBlit2 + filter*: VkFilter + VkBlitImageInfo2KHR* = object + VkCopyBufferToImageInfo2* = object + sType*: VkStructureType + pNext*: pointer + srcBuffer*: VkBuffer + dstImage*: VkImage + dstImageLayout*: VkImageLayout + regionCount*: uint32 + pRegions*: ptr VkBufferImageCopy2 + VkCopyBufferToImageInfo2KHR* = object + VkCopyImageToBufferInfo2* = object + sType*: VkStructureType + pNext*: pointer + srcImage*: VkImage + srcImageLayout*: VkImageLayout + dstBuffer*: VkBuffer + regionCount*: uint32 + pRegions*: ptr VkBufferImageCopy2 + VkCopyImageToBufferInfo2KHR* = object + VkResolveImageInfo2* = object + sType*: VkStructureType + pNext*: pointer + srcImage*: VkImage + srcImageLayout*: VkImageLayout + dstImage*: VkImage + dstImageLayout*: VkImageLayout + regionCount*: uint32 + pRegions*: ptr VkImageResolve2 + VkResolveImageInfo2KHR* = object + VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + shaderImageInt64Atomics*: VkBool32 + sparseImageInt64Atomics*: VkBool32 + VkFragmentShadingRateAttachmentInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pFragmentShadingRateAttachment*: ptr VkAttachmentReference2 + shadingRateAttachmentTexelSize*: VkExtent2D + VkPipelineFragmentShadingRateStateCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + fragmentSize*: VkExtent2D + combinerOps*: array[2, VkFragmentShadingRateCombinerOpKHR] + VkPhysicalDeviceFragmentShadingRateFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + pipelineFragmentShadingRate*: VkBool32 + primitiveFragmentShadingRate*: VkBool32 + attachmentFragmentShadingRate*: VkBool32 + VkPhysicalDeviceFragmentShadingRatePropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + minFragmentShadingRateAttachmentTexelSize*: VkExtent2D + maxFragmentShadingRateAttachmentTexelSize*: VkExtent2D + maxFragmentShadingRateAttachmentTexelSizeAspectRatio*: uint32 + primitiveFragmentShadingRateWithMultipleViewports*: VkBool32 + layeredShadingRateAttachments*: VkBool32 + fragmentShadingRateNonTrivialCombinerOps*: VkBool32 + maxFragmentSize*: VkExtent2D + maxFragmentSizeAspectRatio*: uint32 + maxFragmentShadingRateCoverageSamples*: uint32 + maxFragmentShadingRateRasterizationSamples*: VkSampleCountFlagBits + fragmentShadingRateWithShaderDepthStencilWrites*: VkBool32 + fragmentShadingRateWithSampleMask*: VkBool32 + fragmentShadingRateWithShaderSampleMask*: VkBool32 + fragmentShadingRateWithConservativeRasterization*: VkBool32 + fragmentShadingRateWithFragmentShaderInterlock*: VkBool32 + fragmentShadingRateWithCustomSampleLocations*: VkBool32 + fragmentShadingRateStrictMultiplyCombiner*: VkBool32 + VkPhysicalDeviceFragmentShadingRateKHR* = object + sType*: VkStructureType + pNext*: pointer + sampleCounts*: VkSampleCountFlags + fragmentSize*: VkExtent2D + VkPhysicalDeviceShaderTerminateInvocationFeatures* = object + sType*: VkStructureType + pNext*: pointer + shaderTerminateInvocation*: VkBool32 + VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR* = object + VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + fragmentShadingRateEnums*: VkBool32 + supersampleFragmentShadingRates*: VkBool32 + noInvocationFragmentShadingRates*: VkBool32 + VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + maxFragmentShadingRateInvocationCount*: VkSampleCountFlagBits + VkPipelineFragmentShadingRateEnumStateCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + shadingRateType*: VkFragmentShadingRateTypeNV + shadingRate*: VkFragmentShadingRateNV + combinerOps*: array[2, VkFragmentShadingRateCombinerOpKHR] + VkAccelerationStructureBuildSizesInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + accelerationStructureSize*: VkDeviceSize + updateScratchSize*: VkDeviceSize + buildScratchSize*: VkDeviceSize + VkPhysicalDeviceImage2DViewOf3DFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + image2DViewOf3D*: VkBool32 + sampler2DViewOf3D*: VkBool32 + VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + imageSlicedViewOf3D*: VkBool32 + VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + mutableDescriptorType*: VkBool32 + VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE* = object + VkMutableDescriptorTypeListEXT* = object + descriptorTypeCount*: uint32 + pDescriptorTypes*: ptr VkDescriptorType + VkMutableDescriptorTypeListVALVE* = object + VkMutableDescriptorTypeCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + mutableDescriptorTypeListCount*: uint32 + pMutableDescriptorTypeLists*: ptr VkMutableDescriptorTypeListEXT + VkMutableDescriptorTypeCreateInfoVALVE* = object + VkPhysicalDeviceDepthClipControlFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + depthClipControl*: VkBool32 + VkPipelineViewportDepthClipControlCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + negativeOneToOne*: VkBool32 + VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + vertexInputDynamicState*: VkBool32 + VkPhysicalDeviceExternalMemoryRDMAFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + externalMemoryRDMA*: VkBool32 + VkVertexInputBindingDescription2EXT* = object + sType*: VkStructureType + pNext*: pointer + binding*: uint32 + stride*: uint32 + inputRate*: VkVertexInputRate + divisor*: uint32 + VkVertexInputAttributeDescription2EXT* = object + sType*: VkStructureType + pNext*: pointer + location*: uint32 + binding*: uint32 + format*: VkFormat + offset*: uint32 + VkPhysicalDeviceColorWriteEnableFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + colorWriteEnable*: VkBool32 + VkPipelineColorWriteCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + attachmentCount*: uint32 + pColorWriteEnables*: ptr VkBool32 + VkMemoryBarrier2* = object + sType*: VkStructureType + pNext*: pointer + srcStageMask*: VkPipelineStageFlags2 + srcAccessMask*: VkAccessFlags2 + dstStageMask*: VkPipelineStageFlags2 + dstAccessMask*: VkAccessFlags2 + VkMemoryBarrier2KHR* = object + VkImageMemoryBarrier2* = object + sType*: VkStructureType + pNext*: pointer + srcStageMask*: VkPipelineStageFlags2 + srcAccessMask*: VkAccessFlags2 + dstStageMask*: VkPipelineStageFlags2 + dstAccessMask*: VkAccessFlags2 + oldLayout*: VkImageLayout + newLayout*: VkImageLayout + srcQueueFamilyIndex*: uint32 + dstQueueFamilyIndex*: uint32 + image*: VkImage + subresourceRange*: VkImageSubresourceRange + VkImageMemoryBarrier2KHR* = object + VkBufferMemoryBarrier2* = object + sType*: VkStructureType + pNext*: pointer + srcStageMask*: VkPipelineStageFlags2 + srcAccessMask*: VkAccessFlags2 + dstStageMask*: VkPipelineStageFlags2 + dstAccessMask*: VkAccessFlags2 + srcQueueFamilyIndex*: uint32 + dstQueueFamilyIndex*: uint32 + buffer*: VkBuffer + offset*: VkDeviceSize + size*: VkDeviceSize + VkBufferMemoryBarrier2KHR* = object + VkDependencyInfo* = object + sType*: VkStructureType + pNext*: pointer + dependencyFlags*: VkDependencyFlags + memoryBarrierCount*: uint32 + pMemoryBarriers*: ptr VkMemoryBarrier2 + bufferMemoryBarrierCount*: uint32 + pBufferMemoryBarriers*: ptr VkBufferMemoryBarrier2 + imageMemoryBarrierCount*: uint32 + pImageMemoryBarriers*: ptr VkImageMemoryBarrier2 + VkDependencyInfoKHR* = object + VkSemaphoreSubmitInfo* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + value*: uint64 + stageMask*: VkPipelineStageFlags2 + deviceIndex*: uint32 + VkSemaphoreSubmitInfoKHR* = object + VkCommandBufferSubmitInfo* = object + sType*: VkStructureType + pNext*: pointer + commandBuffer*: VkCommandBuffer + deviceMask*: uint32 + VkCommandBufferSubmitInfoKHR* = object + VkSubmitInfo2* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkSubmitFlags + waitSemaphoreInfoCount*: uint32 + pWaitSemaphoreInfos*: ptr VkSemaphoreSubmitInfo + commandBufferInfoCount*: uint32 + pCommandBufferInfos*: ptr VkCommandBufferSubmitInfo + signalSemaphoreInfoCount*: uint32 + pSignalSemaphoreInfos*: ptr VkSemaphoreSubmitInfo + VkSubmitInfo2KHR* = object + VkQueueFamilyCheckpointProperties2NV* = object + sType*: VkStructureType + pNext*: pointer + checkpointExecutionStageMask*: VkPipelineStageFlags2 + VkCheckpointData2NV* = object + sType*: VkStructureType + pNext*: pointer + stage*: VkPipelineStageFlags2 + pCheckpointMarker*: pointer + VkPhysicalDeviceSynchronization2Features* = object + sType*: VkStructureType + pNext*: pointer + synchronization2*: VkBool32 + VkPhysicalDeviceSynchronization2FeaturesKHR* = object + VkPhysicalDeviceVulkanSC10Properties* = object + sType*: VkStructureType + pNext*: pointer + deviceNoDynamicHostAllocations*: VkBool32 + deviceDestroyFreesMemory*: VkBool32 + commandPoolMultipleCommandBuffersRecording*: VkBool32 + commandPoolResetCommandBuffer*: VkBool32 + commandBufferSimultaneousUse*: VkBool32 + secondaryCommandBufferNullOrImagelessFramebuffer*: VkBool32 + recycleDescriptorSetMemory*: VkBool32 + recyclePipelineMemory*: VkBool32 + maxRenderPassSubpasses*: uint32 + maxRenderPassDependencies*: uint32 + maxSubpassInputAttachments*: uint32 + maxSubpassPreserveAttachments*: uint32 + maxFramebufferAttachments*: uint32 + maxDescriptorSetLayoutBindings*: uint32 + maxQueryFaultCount*: uint32 + maxCallbackFaultCount*: uint32 + maxCommandPoolCommandBuffers*: uint32 + maxCommandBufferSize*: VkDeviceSize + VkPipelinePoolSize* = object + sType*: VkStructureType + pNext*: pointer + poolEntrySize*: VkDeviceSize + poolEntryCount*: uint32 + VkDeviceObjectReservationCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + pipelineCacheCreateInfoCount*: uint32 + pPipelineCacheCreateInfos*: ptr VkPipelineCacheCreateInfo + pipelinePoolSizeCount*: uint32 + pPipelinePoolSizes*: ptr VkPipelinePoolSize + semaphoreRequestCount*: uint32 + commandBufferRequestCount*: uint32 + fenceRequestCount*: uint32 + deviceMemoryRequestCount*: uint32 + bufferRequestCount*: uint32 + imageRequestCount*: uint32 + eventRequestCount*: uint32 + queryPoolRequestCount*: uint32 + bufferViewRequestCount*: uint32 + imageViewRequestCount*: uint32 + layeredImageViewRequestCount*: uint32 + pipelineCacheRequestCount*: uint32 + pipelineLayoutRequestCount*: uint32 + renderPassRequestCount*: uint32 + graphicsPipelineRequestCount*: uint32 + computePipelineRequestCount*: uint32 + descriptorSetLayoutRequestCount*: uint32 + samplerRequestCount*: uint32 + descriptorPoolRequestCount*: uint32 + descriptorSetRequestCount*: uint32 + framebufferRequestCount*: uint32 + commandPoolRequestCount*: uint32 + samplerYcbcrConversionRequestCount*: uint32 + surfaceRequestCount*: uint32 + swapchainRequestCount*: uint32 + displayModeRequestCount*: uint32 + subpassDescriptionRequestCount*: uint32 + attachmentDescriptionRequestCount*: uint32 + descriptorSetLayoutBindingRequestCount*: uint32 + descriptorSetLayoutBindingLimit*: uint32 + maxImageViewMipLevels*: uint32 + maxImageViewArrayLayers*: uint32 + maxLayeredImageViewMipLevels*: uint32 + maxOcclusionQueriesPerPool*: uint32 + maxPipelineStatisticsQueriesPerPool*: uint32 + maxTimestampQueriesPerPool*: uint32 + maxImmutableSamplersPerDescriptorSetLayout*: uint32 + VkCommandPoolMemoryReservationCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + commandPoolReservedSize*: VkDeviceSize + commandPoolMaxCommandBuffers*: uint32 + VkCommandPoolMemoryConsumption* = object + sType*: VkStructureType + pNext*: pointer + commandPoolAllocated*: VkDeviceSize + commandPoolReservedSize*: VkDeviceSize + commandBufferAllocated*: VkDeviceSize + VkPhysicalDeviceVulkanSC10Features* = object + sType*: VkStructureType + pNext*: pointer + shaderAtomicInstructions*: VkBool32 + VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + primitivesGeneratedQuery*: VkBool32 + primitivesGeneratedQueryWithRasterizerDiscard*: VkBool32 + primitivesGeneratedQueryWithNonZeroStreams*: VkBool32 + VkPhysicalDeviceLegacyDitheringFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + legacyDithering*: VkBool32 + VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + multisampledRenderToSingleSampled*: VkBool32 + VkSubpassResolvePerformanceQueryEXT* = object + sType*: VkStructureType + pNext*: pointer + optimal*: VkBool32 + VkMultisampledRenderToSingleSampledInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + multisampledRenderToSingleSampledEnable*: VkBool32 + rasterizationSamples*: VkSampleCountFlagBits + VkPhysicalDevicePipelineProtectedAccessFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + pipelineProtectedAccess*: VkBool32 + VkPhysicalDeviceInheritedViewportScissorFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + inheritedViewportScissor2D*: VkBool32 + VkCommandBufferInheritanceViewportScissorInfoNV* = object + sType*: VkStructureType + pNext*: pointer + viewportScissor2D*: VkBool32 + viewportDepthCount*: uint32 + pViewportDepths*: ptr VkViewport + VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + ycbcr2plane444Formats*: VkBool32 + VkPhysicalDeviceProvokingVertexFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + provokingVertexLast*: VkBool32 + transformFeedbackPreservesProvokingVertex*: VkBool32 + VkPhysicalDeviceProvokingVertexPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + provokingVertexModePerPipeline*: VkBool32 + transformFeedbackPreservesTriangleFanProvokingVertex*: VkBool32 + VkPipelineRasterizationProvokingVertexStateCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + provokingVertexMode*: VkProvokingVertexModeEXT + VkCuModuleCreateInfoNVX* = object + sType*: VkStructureType + pNext*: pointer + dataSize*: csize_t + pData*: pointer + VkCuFunctionCreateInfoNVX* = object + sType*: VkStructureType + pNext*: pointer + module*: VkCuModuleNVX + pName*: cstring + VkCuLaunchInfoNVX* = object + sType*: VkStructureType + pNext*: pointer + function*: VkCuFunctionNVX + gridDimX*: uint32 + gridDimY*: uint32 + gridDimZ*: uint32 + blockDimX*: uint32 + blockDimY*: uint32 + blockDimZ*: uint32 + sharedMemBytes*: uint32 + paramCount*: csize_t + pParams*: ptr pointer + extraCount*: csize_t + pExtras*: ptr pointer + VkPhysicalDeviceDescriptorBufferFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + descriptorBuffer*: VkBool32 + descriptorBufferCaptureReplay*: VkBool32 + descriptorBufferImageLayoutIgnored*: VkBool32 + descriptorBufferPushDescriptors*: VkBool32 + VkPhysicalDeviceDescriptorBufferPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + combinedImageSamplerDescriptorSingleArray*: VkBool32 + bufferlessPushDescriptors*: VkBool32 + allowSamplerImageViewPostSubmitCreation*: VkBool32 + descriptorBufferOffsetAlignment*: VkDeviceSize + maxDescriptorBufferBindings*: uint32 + maxResourceDescriptorBufferBindings*: uint32 + maxSamplerDescriptorBufferBindings*: uint32 + maxEmbeddedImmutableSamplerBindings*: uint32 + maxEmbeddedImmutableSamplers*: uint32 + bufferCaptureReplayDescriptorDataSize*: csize_t + imageCaptureReplayDescriptorDataSize*: csize_t + imageViewCaptureReplayDescriptorDataSize*: csize_t + samplerCaptureReplayDescriptorDataSize*: csize_t + accelerationStructureCaptureReplayDescriptorDataSize*: csize_t + samplerDescriptorSize*: csize_t + combinedImageSamplerDescriptorSize*: csize_t + sampledImageDescriptorSize*: csize_t + storageImageDescriptorSize*: csize_t + uniformTexelBufferDescriptorSize*: csize_t + robustUniformTexelBufferDescriptorSize*: csize_t + storageTexelBufferDescriptorSize*: csize_t + robustStorageTexelBufferDescriptorSize*: csize_t + uniformBufferDescriptorSize*: csize_t + robustUniformBufferDescriptorSize*: csize_t + storageBufferDescriptorSize*: csize_t + robustStorageBufferDescriptorSize*: csize_t + inputAttachmentDescriptorSize*: csize_t + accelerationStructureDescriptorSize*: csize_t + maxSamplerDescriptorBufferRange*: VkDeviceSize + maxResourceDescriptorBufferRange*: VkDeviceSize + samplerDescriptorBufferAddressSpaceSize*: VkDeviceSize + resourceDescriptorBufferAddressSpaceSize*: VkDeviceSize + descriptorBufferAddressSpaceSize*: VkDeviceSize + VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + combinedImageSamplerDensityMapDescriptorSize*: csize_t + VkDescriptorAddressInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + address*: VkDeviceAddress + range*: VkDeviceSize + format*: VkFormat + VkDescriptorBufferBindingInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + address*: VkDeviceAddress + usage*: VkBufferUsageFlags + VkDescriptorBufferBindingPushDescriptorBufferHandleEXT* = object + sType*: VkStructureType + pNext*: pointer + buffer*: VkBuffer + VkDescriptorDataEXT* {.union.} = object + pSampler*: ptr VkSampler + pCombinedImageSampler*: ptr VkDescriptorImageInfo + pInputAttachmentImage*: ptr VkDescriptorImageInfo + pSampledImage*: ptr VkDescriptorImageInfo + pStorageImage*: ptr VkDescriptorImageInfo + pUniformTexelBuffer*: ptr VkDescriptorAddressInfoEXT + pStorageTexelBuffer*: ptr VkDescriptorAddressInfoEXT + pUniformBuffer*: ptr VkDescriptorAddressInfoEXT + pStorageBuffer*: ptr VkDescriptorAddressInfoEXT + accelerationStructure*: VkDeviceAddress + VkDescriptorGetInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + thetype*: VkDescriptorType + data*: VkDescriptorDataEXT + VkBufferCaptureDescriptorDataInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + buffer*: VkBuffer + VkImageCaptureDescriptorDataInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + image*: VkImage + VkImageViewCaptureDescriptorDataInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + imageView*: VkImageView + VkSamplerCaptureDescriptorDataInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + sampler*: VkSampler + VkAccelerationStructureCaptureDescriptorDataInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + accelerationStructure*: VkAccelerationStructureKHR + accelerationStructureNV*: VkAccelerationStructureNV + VkOpaqueCaptureDescriptorDataCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + opaqueCaptureDescriptorData*: pointer + VkPhysicalDeviceShaderIntegerDotProductFeatures* = object + sType*: VkStructureType + pNext*: pointer + shaderIntegerDotProduct*: VkBool32 + VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR* = object + VkPhysicalDeviceShaderIntegerDotProductProperties* = object + sType*: VkStructureType + pNext*: pointer + integerDotProduct8BitUnsignedAccelerated*: VkBool32 + integerDotProduct8BitSignedAccelerated*: VkBool32 + integerDotProduct8BitMixedSignednessAccelerated*: VkBool32 + integerDotProduct4x8BitPackedUnsignedAccelerated*: VkBool32 + integerDotProduct4x8BitPackedSignedAccelerated*: VkBool32 + integerDotProduct4x8BitPackedMixedSignednessAccelerated*: VkBool32 + integerDotProduct16BitUnsignedAccelerated*: VkBool32 + integerDotProduct16BitSignedAccelerated*: VkBool32 + integerDotProduct16BitMixedSignednessAccelerated*: VkBool32 + integerDotProduct32BitUnsignedAccelerated*: VkBool32 + integerDotProduct32BitSignedAccelerated*: VkBool32 + integerDotProduct32BitMixedSignednessAccelerated*: VkBool32 + integerDotProduct64BitUnsignedAccelerated*: VkBool32 + integerDotProduct64BitSignedAccelerated*: VkBool32 + integerDotProduct64BitMixedSignednessAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating8BitUnsignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating8BitSignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating16BitUnsignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating16BitSignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating32BitUnsignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating32BitSignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating64BitUnsignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating64BitSignedAccelerated*: VkBool32 + integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated*: VkBool32 + VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR* = object + VkPhysicalDeviceDrmPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + hasPrimary*: VkBool32 + hasRender*: VkBool32 + primaryMajor*: int64 + primaryMinor*: int64 + renderMajor*: int64 + renderMinor*: int64 + VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + fragmentShaderBarycentric*: VkBool32 + VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + triStripVertexOrderIndependentOfProvokingVertex*: VkBool32 + VkPhysicalDeviceRayTracingMotionBlurFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + rayTracingMotionBlur*: VkBool32 + rayTracingMotionBlurPipelineTraceRaysIndirect*: VkBool32 + VkAccelerationStructureGeometryMotionTrianglesDataNV* = object + sType*: VkStructureType + pNext*: pointer + vertexData*: VkDeviceOrHostAddressConstKHR + VkAccelerationStructureMotionInfoNV* = object + sType*: VkStructureType + pNext*: pointer + maxInstances*: uint32 + flags*: VkAccelerationStructureMotionInfoFlagsNV + VkSRTDataNV* = object + sx*: float32 + a*: float32 + b*: float32 + pvx*: float32 + sy*: float32 + c*: float32 + pvy*: float32 + sz*: float32 + pvz*: float32 + qx*: float32 + qy*: float32 + qz*: float32 + qw*: float32 + tx*: float32 + ty*: float32 + tz*: float32 + VkAccelerationStructureSRTMotionInstanceNV* = object + transformT0*: VkSRTDataNV + transformT1*: VkSRTDataNV + instanceCustomIndex*: uint32 + mask*: uint32 + instanceShaderBindingTableRecordOffset*: uint32 + flags*: VkGeometryInstanceFlagsKHR + accelerationStructureReference*: uint64 + VkAccelerationStructureMatrixMotionInstanceNV* = object + transformT0*: VkTransformMatrixKHR + transformT1*: VkTransformMatrixKHR + instanceCustomIndex*: uint32 + mask*: uint32 + instanceShaderBindingTableRecordOffset*: uint32 + flags*: VkGeometryInstanceFlagsKHR + accelerationStructureReference*: uint64 + VkAccelerationStructureMotionInstanceDataNV* {.union.} = object + staticInstance*: VkAccelerationStructureInstanceKHR + matrixMotionInstance*: VkAccelerationStructureMatrixMotionInstanceNV + srtMotionInstance*: VkAccelerationStructureSRTMotionInstanceNV + VkAccelerationStructureMotionInstanceNV* = object + thetype*: VkAccelerationStructureMotionInstanceTypeNV + flags*: VkAccelerationStructureMotionInstanceFlagsNV + data*: VkAccelerationStructureMotionInstanceDataNV + VkMemoryGetRemoteAddressInfoNV* = object + sType*: VkStructureType + pNext*: pointer + memory*: VkDeviceMemory + handleType*: VkExternalMemoryHandleTypeFlagBits + VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + formatRgba10x6WithoutYCbCrSampler*: VkBool32 + VkFormatProperties3* = object + sType*: VkStructureType + pNext*: pointer + linearTilingFeatures*: VkFormatFeatureFlags2 + optimalTilingFeatures*: VkFormatFeatureFlags2 + bufferFeatures*: VkFormatFeatureFlags2 + VkFormatProperties3KHR* = object + VkDrmFormatModifierPropertiesList2EXT* = object + sType*: VkStructureType + pNext*: pointer + drmFormatModifierCount*: uint32 + pDrmFormatModifierProperties*: ptr VkDrmFormatModifierProperties2EXT + VkDrmFormatModifierProperties2EXT* = object + drmFormatModifier*: uint64 + drmFormatModifierPlaneCount*: uint32 + drmFormatModifierTilingFeatures*: VkFormatFeatureFlags2 + VkPipelineRenderingCreateInfo* = object + sType*: VkStructureType + pNext*: pointer + viewMask*: uint32 + colorAttachmentCount*: uint32 + pColorAttachmentFormats*: ptr VkFormat + depthAttachmentFormat*: VkFormat + stencilAttachmentFormat*: VkFormat + VkPipelineRenderingCreateInfoKHR* = object + VkRenderingInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkRenderingFlags + renderArea*: VkRect2D + layerCount*: uint32 + viewMask*: uint32 + colorAttachmentCount*: uint32 + pColorAttachments*: ptr VkRenderingAttachmentInfo + pDepthAttachment*: ptr VkRenderingAttachmentInfo + pStencilAttachment*: ptr VkRenderingAttachmentInfo + VkRenderingInfoKHR* = object + VkRenderingAttachmentInfo* = object + sType*: VkStructureType + pNext*: pointer + imageView*: VkImageView + imageLayout*: VkImageLayout + resolveMode*: VkResolveModeFlagBits + resolveImageView*: VkImageView + resolveImageLayout*: VkImageLayout + loadOp*: VkAttachmentLoadOp + storeOp*: VkAttachmentStoreOp + clearValue*: VkClearValue + VkRenderingAttachmentInfoKHR* = object + VkRenderingFragmentShadingRateAttachmentInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + imageView*: VkImageView + imageLayout*: VkImageLayout + shadingRateAttachmentTexelSize*: VkExtent2D + VkRenderingFragmentDensityMapAttachmentInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + imageView*: VkImageView + imageLayout*: VkImageLayout + VkPhysicalDeviceDynamicRenderingFeatures* = object + sType*: VkStructureType + pNext*: pointer + dynamicRendering*: VkBool32 + VkPhysicalDeviceDynamicRenderingFeaturesKHR* = object + VkCommandBufferInheritanceRenderingInfo* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkRenderingFlags + viewMask*: uint32 + colorAttachmentCount*: uint32 + pColorAttachmentFormats*: ptr VkFormat + depthAttachmentFormat*: VkFormat + stencilAttachmentFormat*: VkFormat + rasterizationSamples*: VkSampleCountFlagBits + VkCommandBufferInheritanceRenderingInfoKHR* = object + VkAttachmentSampleCountInfoAMD* = object + sType*: VkStructureType + pNext*: pointer + colorAttachmentCount*: uint32 + pColorAttachmentSamples*: ptr VkSampleCountFlagBits + depthStencilAttachmentSamples*: VkSampleCountFlagBits + VkAttachmentSampleCountInfoNV* = object + VkMultiviewPerViewAttributesInfoNVX* = object + sType*: VkStructureType + pNext*: pointer + perViewAttributes*: VkBool32 + perViewAttributesPositionXOnly*: VkBool32 + VkPhysicalDeviceImageViewMinLodFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + minLod*: VkBool32 + VkImageViewMinLodCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + minLod*: float32 + VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + rasterizationOrderColorAttachmentAccess*: VkBool32 + rasterizationOrderDepthAttachmentAccess*: VkBool32 + rasterizationOrderStencilAttachmentAccess*: VkBool32 + VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM* = object + VkPhysicalDeviceLinearColorAttachmentFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + linearColorAttachment*: VkBool32 + VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + graphicsPipelineLibrary*: VkBool32 + VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + graphicsPipelineLibraryFastLinking*: VkBool32 + graphicsPipelineLibraryIndependentInterpolationDecoration*: VkBool32 + VkGraphicsPipelineLibraryCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkGraphicsPipelineLibraryFlagsEXT + VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE* = object + sType*: VkStructureType + pNext*: pointer + descriptorSetHostMapping*: VkBool32 + VkDescriptorSetBindingReferenceVALVE* = object + sType*: VkStructureType + pNext*: pointer + descriptorSetLayout*: VkDescriptorSetLayout + binding*: uint32 + VkDescriptorSetLayoutHostMappingInfoVALVE* = object + sType*: VkStructureType + pNext*: pointer + descriptorOffset*: csize_t + descriptorSize*: uint32 + VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + shaderModuleIdentifier*: VkBool32 + VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + shaderModuleIdentifierAlgorithmUUID*: array[VK_UUID_SIZE, uint8] + VkPipelineShaderStageModuleIdentifierCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + identifierSize*: uint32 + pIdentifier*: ptr uint8 + VkShaderModuleIdentifierEXT* = object + sType*: VkStructureType + pNext*: pointer + identifierSize*: uint32 + identifier*: array[VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT, uint8] + VkImageCompressionControlEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkImageCompressionFlagsEXT + compressionControlPlaneCount*: uint32 + pFixedRateFlags*: ptr VkImageCompressionFixedRateFlagsEXT + VkPhysicalDeviceImageCompressionControlFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + imageCompressionControl*: VkBool32 + VkImageCompressionPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + imageCompressionFlags*: VkImageCompressionFlagsEXT + imageCompressionFixedRateFlags*: VkImageCompressionFixedRateFlagsEXT + VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + imageCompressionControlSwapchain*: VkBool32 + VkImageSubresource2EXT* = object + sType*: VkStructureType + pNext*: pointer + imageSubresource*: VkImageSubresource + VkSubresourceLayout2EXT* = object + sType*: VkStructureType + pNext*: pointer + subresourceLayout*: VkSubresourceLayout + VkRenderPassCreationControlEXT* = object + sType*: VkStructureType + pNext*: pointer + disallowMerging*: VkBool32 + VkRenderPassCreationFeedbackInfoEXT* = object + postMergeSubpassCount*: uint32 + VkRenderPassCreationFeedbackCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + pRenderPassFeedback*: ptr VkRenderPassCreationFeedbackInfoEXT + VkRenderPassSubpassFeedbackInfoEXT* = object + subpassMergeStatus*: VkSubpassMergeStatusEXT + description*: array[VK_MAX_DESCRIPTION_SIZE, char] + postMergeIndex*: uint32 + VkRenderPassSubpassFeedbackCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + pSubpassFeedback*: ptr VkRenderPassSubpassFeedbackInfoEXT + VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + subpassMergeFeedback*: VkBool32 + VkMicromapBuildInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + thetype*: VkMicromapTypeEXT + flags*: VkBuildMicromapFlagsEXT + mode*: VkBuildMicromapModeEXT + dstMicromap*: VkMicromapEXT + usageCountsCount*: uint32 + pUsageCounts*: ptr VkMicromapUsageEXT + ppUsageCounts*: ptr ptr VkMicromapUsageEXT + data*: VkDeviceOrHostAddressConstKHR + scratchData*: VkDeviceOrHostAddressKHR + triangleArray*: VkDeviceOrHostAddressConstKHR + triangleArrayStride*: VkDeviceSize + VkMicromapCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + createFlags*: VkMicromapCreateFlagsEXT + buffer*: VkBuffer + offset*: VkDeviceSize + size*: VkDeviceSize + thetype*: VkMicromapTypeEXT + deviceAddress*: VkDeviceAddress + VkMicromapVersionInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + pVersionData*: ptr uint8 + VkCopyMicromapInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + src*: VkMicromapEXT + dst*: VkMicromapEXT + mode*: VkCopyMicromapModeEXT + VkCopyMicromapToMemoryInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + src*: VkMicromapEXT + dst*: VkDeviceOrHostAddressKHR + mode*: VkCopyMicromapModeEXT + VkCopyMemoryToMicromapInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + src*: VkDeviceOrHostAddressConstKHR + dst*: VkMicromapEXT + mode*: VkCopyMicromapModeEXT + VkMicromapBuildSizesInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + micromapSize*: VkDeviceSize + buildScratchSize*: VkDeviceSize + discardable*: VkBool32 + VkMicromapUsageEXT* = object + count*: uint32 + subdivisionLevel*: uint32 + format*: uint32 + VkMicromapTriangleEXT* = object + dataOffset*: uint32 + subdivisionLevel*: uint16 + format*: uint16 + VkPhysicalDeviceOpacityMicromapFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + micromap*: VkBool32 + micromapCaptureReplay*: VkBool32 + micromapHostCommands*: VkBool32 + VkPhysicalDeviceOpacityMicromapPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + maxOpacity2StateSubdivisionLevel*: uint32 + maxOpacity4StateSubdivisionLevel*: uint32 + VkAccelerationStructureTrianglesOpacityMicromapEXT* = object + sType*: VkStructureType + pNext*: pointer + indexType*: VkIndexType + indexBuffer*: VkDeviceOrHostAddressConstKHR + indexStride*: VkDeviceSize + baseTriangle*: uint32 + usageCountsCount*: uint32 + pUsageCounts*: ptr VkMicromapUsageEXT + ppUsageCounts*: ptr ptr VkMicromapUsageEXT + micromap*: VkMicromapEXT + VkPipelinePropertiesIdentifierEXT* = object + sType*: VkStructureType + pNext*: pointer + pipelineIdentifier*: array[VK_UUID_SIZE, uint8] + VkPhysicalDevicePipelinePropertiesFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + pipelinePropertiesIdentifier*: VkBool32 + VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD* = object + sType*: VkStructureType + pNext*: pointer + shaderEarlyAndLateFragmentTests*: VkBool32 + VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + nonSeamlessCubeMap*: VkBool32 + VkPhysicalDevicePipelineRobustnessFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + pipelineRobustness*: VkBool32 + VkPipelineRobustnessCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + storageBuffers*: VkPipelineRobustnessBufferBehaviorEXT + uniformBuffers*: VkPipelineRobustnessBufferBehaviorEXT + vertexInputs*: VkPipelineRobustnessBufferBehaviorEXT + images*: VkPipelineRobustnessImageBehaviorEXT + VkPhysicalDevicePipelineRobustnessPropertiesEXT* = object + sType*: VkStructureType + pNext*: pointer + defaultRobustnessStorageBuffers*: VkPipelineRobustnessBufferBehaviorEXT + defaultRobustnessUniformBuffers*: VkPipelineRobustnessBufferBehaviorEXT + defaultRobustnessVertexInputs*: VkPipelineRobustnessBufferBehaviorEXT + defaultRobustnessImages*: VkPipelineRobustnessImageBehaviorEXT + VkImageViewSampleWeightCreateInfoQCOM* = object + sType*: VkStructureType + pNext*: pointer + filterCenter*: VkOffset2D + filterSize*: VkExtent2D + numPhases*: uint32 + VkPhysicalDeviceImageProcessingFeaturesQCOM* = object + sType*: VkStructureType + pNext*: pointer + textureSampleWeighted*: VkBool32 + textureBoxFilter*: VkBool32 + textureBlockMatch*: VkBool32 + VkPhysicalDeviceImageProcessingPropertiesQCOM* = object + sType*: VkStructureType + pNext*: pointer + maxWeightFilterPhases*: uint32 + maxWeightFilterDimension*: VkExtent2D + maxBlockMatchRegion*: VkExtent2D + maxBoxFilterBlockSize*: VkExtent2D + VkPhysicalDeviceTilePropertiesFeaturesQCOM* = object + sType*: VkStructureType + pNext*: pointer + tileProperties*: VkBool32 + VkTilePropertiesQCOM* = object + sType*: VkStructureType + pNext*: pointer + tileSize*: VkExtent3D + apronSize*: VkExtent2D + origin*: VkOffset2D + VkPhysicalDeviceAmigoProfilingFeaturesSEC* = object + sType*: VkStructureType + pNext*: pointer + amigoProfiling*: VkBool32 + VkAmigoProfilingSubmitInfoSEC* = object + sType*: VkStructureType + pNext*: pointer + firstDrawTimestamp*: uint64 + swapBufferTimestamp*: uint64 + VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + attachmentFeedbackLoopLayout*: VkBool32 + VkPhysicalDeviceDepthClampZeroOneFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + depthClampZeroOne*: VkBool32 + VkPhysicalDeviceAddressBindingReportFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + reportAddressBinding*: VkBool32 + VkDeviceAddressBindingCallbackDataEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDeviceAddressBindingFlagsEXT + baseAddress*: VkDeviceAddress + size*: VkDeviceSize + bindingType*: VkDeviceAddressBindingTypeEXT + VkPhysicalDeviceOpticalFlowFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + opticalFlow*: VkBool32 + VkPhysicalDeviceOpticalFlowPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + supportedOutputGridSizes*: VkOpticalFlowGridSizeFlagsNV + supportedHintGridSizes*: VkOpticalFlowGridSizeFlagsNV + hintSupported*: VkBool32 + costSupported*: VkBool32 + bidirectionalFlowSupported*: VkBool32 + globalFlowSupported*: VkBool32 + minWidth*: uint32 + minHeight*: uint32 + maxWidth*: uint32 + maxHeight*: uint32 + maxNumRegionsOfInterest*: uint32 + VkOpticalFlowImageFormatInfoNV* = object + sType*: VkStructureType + pNext*: pointer + usage*: VkOpticalFlowUsageFlagsNV + VkOpticalFlowImageFormatPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + format*: VkFormat + VkOpticalFlowSessionCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + width*: uint32 + height*: uint32 + imageFormat*: VkFormat + flowVectorFormat*: VkFormat + costFormat*: VkFormat + outputGridSize*: VkOpticalFlowGridSizeFlagsNV + hintGridSize*: VkOpticalFlowGridSizeFlagsNV + performanceLevel*: VkOpticalFlowPerformanceLevelNV + flags*: VkOpticalFlowSessionCreateFlagsNV + VkOpticalFlowSessionCreatePrivateDataInfoNV* = object + sType*: VkStructureType + pNext*: pointer + id*: uint32 + size*: uint32 + pPrivateData*: pointer + VkOpticalFlowExecuteInfoNV* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkOpticalFlowExecuteFlagsNV + regionCount*: uint32 + pRegions*: ptr VkRect2D + VkPhysicalDeviceFaultFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + deviceFault*: VkBool32 + deviceFaultVendorBinary*: VkBool32 + VkDeviceFaultAddressInfoEXT* = object + addressType*: VkDeviceFaultAddressTypeEXT + reportedAddress*: VkDeviceAddress + addressPrecision*: VkDeviceSize + VkDeviceFaultVendorInfoEXT* = object + description*: array[VK_MAX_DESCRIPTION_SIZE, char] + vendorFaultCode*: uint64 + vendorFaultData*: uint64 + VkDeviceFaultCountsEXT* = object + sType*: VkStructureType + pNext*: pointer + addressInfoCount*: uint32 + vendorInfoCount*: uint32 + vendorBinarySize*: VkDeviceSize + VkDeviceFaultInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + description*: array[VK_MAX_DESCRIPTION_SIZE, char] + pAddressInfos*: ptr VkDeviceFaultAddressInfoEXT + pVendorInfos*: ptr VkDeviceFaultVendorInfoEXT + pVendorBinaryData*: pointer + VkDeviceFaultVendorBinaryHeaderVersionOneEXT* = object + headerSize*: uint32 + headerVersion*: VkDeviceFaultVendorBinaryHeaderVersionEXT + vendorID*: uint32 + deviceID*: uint32 + driverVersion*: uint32 + pipelineCacheUUID*: array[VK_UUID_SIZE, uint8] + applicationNameOffset*: uint32 + applicationVersion*: uint32 + engineNameOffset*: uint32 + VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + pipelineLibraryGroupHandles*: VkBool32 + VkDecompressMemoryRegionNV* = object + srcAddress*: VkDeviceAddress + dstAddress*: VkDeviceAddress + compressedSize*: VkDeviceSize + decompressedSize*: VkDeviceSize + decompressionMethod*: VkMemoryDecompressionMethodFlagsNV + VkPhysicalDeviceShaderCoreBuiltinsPropertiesARM* = object + sType*: VkStructureType + pNext*: pointer + shaderCoreMask*: uint64 + shaderCoreCount*: uint32 + shaderWarpsPerCore*: uint32 + VkPhysicalDeviceShaderCoreBuiltinsFeaturesARM* = object + sType*: VkStructureType + pNext*: pointer + shaderCoreBuiltins*: VkBool32 + VkSurfacePresentModeEXT* = object + sType*: VkStructureType + pNext*: pointer + presentMode*: VkPresentModeKHR + VkSurfacePresentScalingCapabilitiesEXT* = object + sType*: VkStructureType + pNext*: pointer + supportedPresentScaling*: VkPresentScalingFlagsEXT + supportedPresentGravityX*: VkPresentGravityFlagsEXT + supportedPresentGravityY*: VkPresentGravityFlagsEXT + minScaledImageExtent*: VkExtent2D + maxScaledImageExtent*: VkExtent2D + VkSurfacePresentModeCompatibilityEXT* = object + sType*: VkStructureType + pNext*: pointer + presentModeCount*: uint32 + pPresentModes*: ptr VkPresentModeKHR + VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT* = object + sType*: VkStructureType + pNext*: pointer + swapchainMaintenance1*: VkBool32 + VkSwapchainPresentFenceInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + swapchainCount*: uint32 + pFences*: ptr VkFence + VkSwapchainPresentModesCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + presentModeCount*: uint32 + pPresentModes*: ptr VkPresentModeKHR + VkSwapchainPresentModeInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + swapchainCount*: uint32 + pPresentModes*: ptr VkPresentModeKHR + VkSwapchainPresentScalingCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + scalingBehavior*: VkPresentScalingFlagsEXT + presentGravityX*: VkPresentGravityFlagsEXT + presentGravityY*: VkPresentGravityFlagsEXT + VkReleaseSwapchainImagesInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + swapchain*: VkSwapchainKHR + imageIndexCount*: uint32 + pImageIndices*: ptr uint32 + VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + rayTracingInvocationReorder*: VkBool32 + VkPhysicalDeviceRayTracingInvocationReorderPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + rayTracingInvocationReorderReorderingHint*: VkRayTracingInvocationReorderModeNV + VkDirectDriverLoadingInfoLUNARG* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDirectDriverLoadingFlagsLUNARG + pfnGetInstanceProcAddr*: PFN_vkGetInstanceProcAddrLUNARG + VkDirectDriverLoadingListLUNARG* = object + sType*: VkStructureType + pNext*: pointer + mode*: VkDirectDriverLoadingModeLUNARG + driverCount*: uint32 + pDrivers*: ptr VkDirectDriverLoadingInfoLUNARG + VkPhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM* = object + sType*: VkStructureType + pNext*: pointer + multiviewPerViewViewports*: VkBool32 + VkPhysicalDeviceShaderCorePropertiesARM* = object + sType*: VkStructureType + pNext*: pointer + pixelRate*: uint32 + texelRate*: uint32 + fmaRate*: uint32 + VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM* = object + sType*: VkStructureType + pNext*: pointer + multiviewPerViewRenderAreas*: VkBool32 + VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM* = object + sType*: VkStructureType + pNext*: pointer + perViewRenderAreaCount*: uint32 + pPerViewRenderAreas*: ptr VkRect2D +# feature VK_VERSION_1_0 +var + vkCreateInstance*: proc(pCreateInfo: ptr VkInstanceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pInstance: ptr VkInstance): VkResult {.stdcall.} + vkDestroyInstance*: proc(instance: VkInstance, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkEnumeratePhysicalDevices*: proc(instance: VkInstance, pPhysicalDeviceCount: ptr uint32, pPhysicalDevices: ptr VkPhysicalDevice): VkResult {.stdcall.} + vkGetPhysicalDeviceFeatures*: proc(physicalDevice: VkPhysicalDevice, pFeatures: ptr VkPhysicalDeviceFeatures): void {.stdcall.} + vkGetPhysicalDeviceFormatProperties*: proc(physicalDevice: VkPhysicalDevice, format: VkFormat, pFormatProperties: ptr VkFormatProperties): void {.stdcall.} + vkGetPhysicalDeviceImageFormatProperties*: proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, tiling: VkImageTiling, usage: VkImageUsageFlags, flags: VkImageCreateFlags, pImageFormatProperties: ptr VkImageFormatProperties): VkResult {.stdcall.} + vkGetPhysicalDeviceProperties*: proc(physicalDevice: VkPhysicalDevice, pProperties: ptr VkPhysicalDeviceProperties): void {.stdcall.} + vkGetPhysicalDeviceQueueFamilyProperties*: proc(physicalDevice: VkPhysicalDevice, pQueueFamilyPropertyCount: ptr uint32, pQueueFamilyProperties: ptr VkQueueFamilyProperties): void {.stdcall.} + vkGetPhysicalDeviceMemoryProperties*: proc(physicalDevice: VkPhysicalDevice, pMemoryProperties: ptr VkPhysicalDeviceMemoryProperties): void {.stdcall.} + vkGetDeviceProcAddr*: proc(device: VkDevice, pName: cstring): PFN_vkVoidFunction {.stdcall.} + vkCreateDevice*: proc(physicalDevice: VkPhysicalDevice, pCreateInfo: ptr VkDeviceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDevice: ptr VkDevice): VkResult {.stdcall.} + vkDestroyDevice*: proc(device: VkDevice, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkEnumerateInstanceExtensionProperties*: proc(pLayerName: cstring, pPropertyCount: ptr uint32, pProperties: ptr VkExtensionProperties): VkResult {.stdcall.} + vkEnumerateDeviceExtensionProperties*: proc(physicalDevice: VkPhysicalDevice, pLayerName: cstring, pPropertyCount: ptr uint32, pProperties: ptr VkExtensionProperties): VkResult {.stdcall.} + vkEnumerateInstanceLayerProperties*: proc(pPropertyCount: ptr uint32, pProperties: ptr VkLayerProperties): VkResult {.stdcall.} + vkEnumerateDeviceLayerProperties*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkLayerProperties): VkResult {.stdcall.} + vkGetDeviceQueue*: proc(device: VkDevice, queueFamilyIndex: uint32, queueIndex: uint32, pQueue: ptr VkQueue): void {.stdcall.} + vkQueueSubmit*: proc(queue: VkQueue, submitCount: uint32, pSubmits: ptr VkSubmitInfo, fence: VkFence): VkResult {.stdcall.} + vkQueueWaitIdle*: proc(queue: VkQueue): VkResult {.stdcall.} + vkDeviceWaitIdle*: proc(device: VkDevice): VkResult {.stdcall.} + vkAllocateMemory*: proc(device: VkDevice, pAllocateInfo: ptr VkMemoryAllocateInfo, pAllocator: ptr VkAllocationCallbacks, pMemory: ptr VkDeviceMemory): VkResult {.stdcall.} + vkFreeMemory*: proc(device: VkDevice, memory: VkDeviceMemory, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkMapMemory*: proc(device: VkDevice, memory: VkDeviceMemory, offset: VkDeviceSize, size: VkDeviceSize, flags: VkMemoryMapFlags, ppData: ptr pointer): VkResult {.stdcall.} + vkUnmapMemory*: proc(device: VkDevice, memory: VkDeviceMemory): void {.stdcall.} + vkFlushMappedMemoryRanges*: proc(device: VkDevice, memoryRangeCount: uint32, pMemoryRanges: ptr VkMappedMemoryRange): VkResult {.stdcall.} + vkInvalidateMappedMemoryRanges*: proc(device: VkDevice, memoryRangeCount: uint32, pMemoryRanges: ptr VkMappedMemoryRange): VkResult {.stdcall.} + vkGetDeviceMemoryCommitment*: proc(device: VkDevice, memory: VkDeviceMemory, pCommittedMemoryInBytes: ptr VkDeviceSize): void {.stdcall.} + vkBindBufferMemory*: proc(device: VkDevice, buffer: VkBuffer, memory: VkDeviceMemory, memoryOffset: VkDeviceSize): VkResult {.stdcall.} + vkBindImageMemory*: proc(device: VkDevice, image: VkImage, memory: VkDeviceMemory, memoryOffset: VkDeviceSize): VkResult {.stdcall.} + vkGetBufferMemoryRequirements*: proc(device: VkDevice, buffer: VkBuffer, pMemoryRequirements: ptr VkMemoryRequirements): void {.stdcall.} + vkGetImageMemoryRequirements*: proc(device: VkDevice, image: VkImage, pMemoryRequirements: ptr VkMemoryRequirements): void {.stdcall.} + vkGetImageSparseMemoryRequirements*: proc(device: VkDevice, image: VkImage, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements): void {.stdcall.} + vkGetPhysicalDeviceSparseImageFormatProperties*: proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, samples: VkSampleCountFlagBits, usage: VkImageUsageFlags, tiling: VkImageTiling, pPropertyCount: ptr uint32, pProperties: ptr VkSparseImageFormatProperties): void {.stdcall.} + vkQueueBindSparse*: proc(queue: VkQueue, bindInfoCount: uint32, pBindInfo: ptr VkBindSparseInfo, fence: VkFence): VkResult {.stdcall.} + vkCreateFence*: proc(device: VkDevice, pCreateInfo: ptr VkFenceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.} + vkDestroyFence*: proc(device: VkDevice, fence: VkFence, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkResetFences*: proc(device: VkDevice, fenceCount: uint32, pFences: ptr VkFence): VkResult {.stdcall.} + vkGetFenceStatus*: proc(device: VkDevice, fence: VkFence): VkResult {.stdcall.} + vkWaitForFences*: proc(device: VkDevice, fenceCount: uint32, pFences: ptr VkFence, waitAll: VkBool32, timeout: uint64): VkResult {.stdcall.} + vkCreateSemaphore*: proc(device: VkDevice, pCreateInfo: ptr VkSemaphoreCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSemaphore: ptr VkSemaphore): VkResult {.stdcall.} + vkDestroySemaphore*: proc(device: VkDevice, semaphore: VkSemaphore, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreateEvent*: proc(device: VkDevice, pCreateInfo: ptr VkEventCreateInfo, pAllocator: ptr VkAllocationCallbacks, pEvent: ptr VkEvent): VkResult {.stdcall.} + vkDestroyEvent*: proc(device: VkDevice, event: VkEvent, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetEventStatus*: proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.} + vkSetEvent*: proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.} + vkResetEvent*: proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.} + vkCreateQueryPool*: proc(device: VkDevice, pCreateInfo: ptr VkQueryPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pQueryPool: ptr VkQueryPool): VkResult {.stdcall.} + vkDestroyQueryPool*: proc(device: VkDevice, queryPool: VkQueryPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetQueryPoolResults*: proc(device: VkDevice, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32, dataSize: csize_t, pData: pointer, stride: VkDeviceSize, flags: VkQueryResultFlags): VkResult {.stdcall.} + vkCreateBuffer*: proc(device: VkDevice, pCreateInfo: ptr VkBufferCreateInfo, pAllocator: ptr VkAllocationCallbacks, pBuffer: ptr VkBuffer): VkResult {.stdcall.} + vkDestroyBuffer*: proc(device: VkDevice, buffer: VkBuffer, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreateBufferView*: proc(device: VkDevice, pCreateInfo: ptr VkBufferViewCreateInfo, pAllocator: ptr VkAllocationCallbacks, pView: ptr VkBufferView): VkResult {.stdcall.} + vkDestroyBufferView*: proc(device: VkDevice, bufferView: VkBufferView, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreateImage*: proc(device: VkDevice, pCreateInfo: ptr VkImageCreateInfo, pAllocator: ptr VkAllocationCallbacks, pImage: ptr VkImage): VkResult {.stdcall.} + vkDestroyImage*: proc(device: VkDevice, image: VkImage, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetImageSubresourceLayout*: proc(device: VkDevice, image: VkImage, pSubresource: ptr VkImageSubresource, pLayout: ptr VkSubresourceLayout): void {.stdcall.} + vkCreateImageView*: proc(device: VkDevice, pCreateInfo: ptr VkImageViewCreateInfo, pAllocator: ptr VkAllocationCallbacks, pView: ptr VkImageView): VkResult {.stdcall.} + vkDestroyImageView*: proc(device: VkDevice, imageView: VkImageView, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreateShaderModule*: proc(device: VkDevice, pCreateInfo: ptr VkShaderModuleCreateInfo, pAllocator: ptr VkAllocationCallbacks, pShaderModule: ptr VkShaderModule): VkResult {.stdcall.} + vkDestroyShaderModule*: proc(device: VkDevice, shaderModule: VkShaderModule, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreatePipelineCache*: proc(device: VkDevice, pCreateInfo: ptr VkPipelineCacheCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelineCache: ptr VkPipelineCache): VkResult {.stdcall.} + vkDestroyPipelineCache*: proc(device: VkDevice, pipelineCache: VkPipelineCache, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetPipelineCacheData*: proc(device: VkDevice, pipelineCache: VkPipelineCache, pDataSize: ptr csize_t, pData: pointer): VkResult {.stdcall.} + vkMergePipelineCaches*: proc(device: VkDevice, dstCache: VkPipelineCache, srcCacheCount: uint32, pSrcCaches: ptr VkPipelineCache): VkResult {.stdcall.} + vkCreateGraphicsPipelines*: proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkGraphicsPipelineCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.} + vkCreateComputePipelines*: proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkComputePipelineCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.} + vkDestroyPipeline*: proc(device: VkDevice, pipeline: VkPipeline, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreatePipelineLayout*: proc(device: VkDevice, pCreateInfo: ptr VkPipelineLayoutCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelineLayout: ptr VkPipelineLayout): VkResult {.stdcall.} + vkDestroyPipelineLayout*: proc(device: VkDevice, pipelineLayout: VkPipelineLayout, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreateSampler*: proc(device: VkDevice, pCreateInfo: ptr VkSamplerCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSampler: ptr VkSampler): VkResult {.stdcall.} + vkDestroySampler*: proc(device: VkDevice, sampler: VkSampler, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreateDescriptorSetLayout*: proc(device: VkDevice, pCreateInfo: ptr VkDescriptorSetLayoutCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSetLayout: ptr VkDescriptorSetLayout): VkResult {.stdcall.} + vkDestroyDescriptorSetLayout*: proc(device: VkDevice, descriptorSetLayout: VkDescriptorSetLayout, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreateDescriptorPool*: proc(device: VkDevice, pCreateInfo: ptr VkDescriptorPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDescriptorPool: ptr VkDescriptorPool): VkResult {.stdcall.} + vkDestroyDescriptorPool*: proc(device: VkDevice, descriptorPool: VkDescriptorPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkResetDescriptorPool*: proc(device: VkDevice, descriptorPool: VkDescriptorPool, flags: VkDescriptorPoolResetFlags): VkResult {.stdcall.} + vkAllocateDescriptorSets*: proc(device: VkDevice, pAllocateInfo: ptr VkDescriptorSetAllocateInfo, pDescriptorSets: ptr VkDescriptorSet): VkResult {.stdcall.} + vkFreeDescriptorSets*: proc(device: VkDevice, descriptorPool: VkDescriptorPool, descriptorSetCount: uint32, pDescriptorSets: ptr VkDescriptorSet): VkResult {.stdcall.} + vkUpdateDescriptorSets*: proc(device: VkDevice, descriptorWriteCount: uint32, pDescriptorWrites: ptr VkWriteDescriptorSet, descriptorCopyCount: uint32, pDescriptorCopies: ptr VkCopyDescriptorSet): void {.stdcall.} + vkCreateFramebuffer*: proc(device: VkDevice, pCreateInfo: ptr VkFramebufferCreateInfo, pAllocator: ptr VkAllocationCallbacks, pFramebuffer: ptr VkFramebuffer): VkResult {.stdcall.} + vkDestroyFramebuffer*: proc(device: VkDevice, framebuffer: VkFramebuffer, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreateRenderPass*: proc(device: VkDevice, pCreateInfo: ptr VkRenderPassCreateInfo, pAllocator: ptr VkAllocationCallbacks, pRenderPass: ptr VkRenderPass): VkResult {.stdcall.} + vkDestroyRenderPass*: proc(device: VkDevice, renderPass: VkRenderPass, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetRenderAreaGranularity*: proc(device: VkDevice, renderPass: VkRenderPass, pGranularity: ptr VkExtent2D): void {.stdcall.} + vkCreateCommandPool*: proc(device: VkDevice, pCreateInfo: ptr VkCommandPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pCommandPool: ptr VkCommandPool): VkResult {.stdcall.} + vkDestroyCommandPool*: proc(device: VkDevice, commandPool: VkCommandPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkResetCommandPool*: proc(device: VkDevice, commandPool: VkCommandPool, flags: VkCommandPoolResetFlags): VkResult {.stdcall.} + vkAllocateCommandBuffers*: proc(device: VkDevice, pAllocateInfo: ptr VkCommandBufferAllocateInfo, pCommandBuffers: ptr VkCommandBuffer): VkResult {.stdcall.} + vkFreeCommandBuffers*: proc(device: VkDevice, commandPool: VkCommandPool, commandBufferCount: uint32, pCommandBuffers: ptr VkCommandBuffer): void {.stdcall.} + vkBeginCommandBuffer*: proc(commandBuffer: VkCommandBuffer, pBeginInfo: ptr VkCommandBufferBeginInfo): VkResult {.stdcall.} + vkEndCommandBuffer*: proc(commandBuffer: VkCommandBuffer): VkResult {.stdcall.} + vkResetCommandBuffer*: proc(commandBuffer: VkCommandBuffer, flags: VkCommandBufferResetFlags): VkResult {.stdcall.} + vkCmdBindPipeline*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, pipeline: VkPipeline): void {.stdcall.} + vkCmdSetViewport*: proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewports: ptr VkViewport): void {.stdcall.} + vkCmdSetScissor*: proc(commandBuffer: VkCommandBuffer, firstScissor: uint32, scissorCount: uint32, pScissors: ptr VkRect2D): void {.stdcall.} + vkCmdSetLineWidth*: proc(commandBuffer: VkCommandBuffer, lineWidth: float32): void {.stdcall.} + vkCmdSetDepthBias*: proc(commandBuffer: VkCommandBuffer, depthBiasConstantFactor: float32, depthBiasClamp: float32, depthBiasSlopeFactor: float32): void {.stdcall.} + vkCmdSetBlendConstants*: proc(commandBuffer: VkCommandBuffer, blendConstants: array[4, float32]): void {.stdcall.} + vkCmdSetDepthBounds*: proc(commandBuffer: VkCommandBuffer, minDepthBounds: float32, maxDepthBounds: float32): void {.stdcall.} + vkCmdSetStencilCompareMask*: proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, compareMask: uint32): void {.stdcall.} + vkCmdSetStencilWriteMask*: proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, writeMask: uint32): void {.stdcall.} + vkCmdSetStencilReference*: proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, reference: uint32): void {.stdcall.} + vkCmdBindDescriptorSets*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, firstSet: uint32, descriptorSetCount: uint32, pDescriptorSets: ptr VkDescriptorSet, dynamicOffsetCount: uint32, pDynamicOffsets: ptr uint32): void {.stdcall.} + vkCmdBindIndexBuffer*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, indexType: VkIndexType): void {.stdcall.} + vkCmdBindVertexBuffers*: proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize): void {.stdcall.} + vkCmdDraw*: proc(commandBuffer: VkCommandBuffer, vertexCount: uint32, instanceCount: uint32, firstVertex: uint32, firstInstance: uint32): void {.stdcall.} + vkCmdDrawIndexed*: proc(commandBuffer: VkCommandBuffer, indexCount: uint32, instanceCount: uint32, firstIndex: uint32, vertexOffset: int32, firstInstance: uint32): void {.stdcall.} + vkCmdDrawIndirect*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.} + vkCmdDrawIndexedIndirect*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.} + vkCmdDispatch*: proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.} + vkCmdDispatchIndirect*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize): void {.stdcall.} + vkCmdCopyBuffer*: proc(commandBuffer: VkCommandBuffer, srcBuffer: VkBuffer, dstBuffer: VkBuffer, regionCount: uint32, pRegions: ptr VkBufferCopy): void {.stdcall.} + vkCmdCopyImage*: proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageCopy): void {.stdcall.} + vkCmdBlitImage*: proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageBlit, filter: VkFilter): void {.stdcall.} + vkCmdCopyBufferToImage*: proc(commandBuffer: VkCommandBuffer, srcBuffer: VkBuffer, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkBufferImageCopy): void {.stdcall.} + vkCmdCopyImageToBuffer*: proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstBuffer: VkBuffer, regionCount: uint32, pRegions: ptr VkBufferImageCopy): void {.stdcall.} + vkCmdUpdateBuffer*: proc(commandBuffer: VkCommandBuffer, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, dataSize: VkDeviceSize, pData: pointer): void {.stdcall.} + vkCmdFillBuffer*: proc(commandBuffer: VkCommandBuffer, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, size: VkDeviceSize, data: uint32): void {.stdcall.} + vkCmdClearColorImage*: proc(commandBuffer: VkCommandBuffer, image: VkImage, imageLayout: VkImageLayout, pColor: ptr VkClearColorValue, rangeCount: uint32, pRanges: ptr VkImageSubresourceRange): void {.stdcall.} + vkCmdClearDepthStencilImage*: proc(commandBuffer: VkCommandBuffer, image: VkImage, imageLayout: VkImageLayout, pDepthStencil: ptr VkClearDepthStencilValue, rangeCount: uint32, pRanges: ptr VkImageSubresourceRange): void {.stdcall.} + vkCmdClearAttachments*: proc(commandBuffer: VkCommandBuffer, attachmentCount: uint32, pAttachments: ptr VkClearAttachment, rectCount: uint32, pRects: ptr VkClearRect): void {.stdcall.} + vkCmdResolveImage*: proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageResolve): void {.stdcall.} + vkCmdSetEvent*: proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags): void {.stdcall.} + vkCmdResetEvent*: proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags): void {.stdcall.} + vkCmdWaitEvents*: proc(commandBuffer: VkCommandBuffer, eventCount: uint32, pEvents: ptr VkEvent, srcStageMask: VkPipelineStageFlags, dstStageMask: VkPipelineStageFlags, memoryBarrierCount: uint32, pMemoryBarriers: ptr VkMemoryBarrier, bufferMemoryBarrierCount: uint32, pBufferMemoryBarriers: ptr VkBufferMemoryBarrier, imageMemoryBarrierCount: uint32, pImageMemoryBarriers: ptr VkImageMemoryBarrier): void {.stdcall.} + vkCmdPipelineBarrier*: proc(commandBuffer: VkCommandBuffer, srcStageMask: VkPipelineStageFlags, dstStageMask: VkPipelineStageFlags, dependencyFlags: VkDependencyFlags, memoryBarrierCount: uint32, pMemoryBarriers: ptr VkMemoryBarrier, bufferMemoryBarrierCount: uint32, pBufferMemoryBarriers: ptr VkBufferMemoryBarrier, imageMemoryBarrierCount: uint32, pImageMemoryBarriers: ptr VkImageMemoryBarrier): void {.stdcall.} + vkCmdBeginQuery*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, flags: VkQueryControlFlags): void {.stdcall.} + vkCmdEndQuery*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32): void {.stdcall.} + vkCmdResetQueryPool*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32): void {.stdcall.} + vkCmdWriteTimestamp*: proc(commandBuffer: VkCommandBuffer, pipelineStage: VkPipelineStageFlagBits, queryPool: VkQueryPool, query: uint32): void {.stdcall.} + vkCmdCopyQueryPoolResults*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, stride: VkDeviceSize, flags: VkQueryResultFlags): void {.stdcall.} + vkCmdPushConstants*: proc(commandBuffer: VkCommandBuffer, layout: VkPipelineLayout, stageFlags: VkShaderStageFlags, offset: uint32, size: uint32, pValues: pointer): void {.stdcall.} + vkCmdBeginRenderPass*: proc(commandBuffer: VkCommandBuffer, pRenderPassBegin: ptr VkRenderPassBeginInfo, contents: VkSubpassContents): void {.stdcall.} + vkCmdNextSubpass*: proc(commandBuffer: VkCommandBuffer, contents: VkSubpassContents): void {.stdcall.} + vkCmdEndRenderPass*: proc(commandBuffer: VkCommandBuffer): void {.stdcall.} + vkCmdExecuteCommands*: proc(commandBuffer: VkCommandBuffer, commandBufferCount: uint32, pCommandBuffers: ptr VkCommandBuffer): void {.stdcall.} +proc loadVK_VERSION_1_0*(instance: VkInstance) = + vkDestroyInstance = cast[proc(instance: VkInstance, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyInstance")) + vkEnumeratePhysicalDevices = cast[proc(instance: VkInstance, pPhysicalDeviceCount: ptr uint32, pPhysicalDevices: ptr VkPhysicalDevice): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices")) + vkGetPhysicalDeviceFeatures = cast[proc(physicalDevice: VkPhysicalDevice, pFeatures: ptr VkPhysicalDeviceFeatures): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures")) + vkGetPhysicalDeviceFormatProperties = cast[proc(physicalDevice: VkPhysicalDevice, format: VkFormat, pFormatProperties: ptr VkFormatProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties")) + vkGetPhysicalDeviceImageFormatProperties = cast[proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, tiling: VkImageTiling, usage: VkImageUsageFlags, flags: VkImageCreateFlags, pImageFormatProperties: ptr VkImageFormatProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties")) + vkGetPhysicalDeviceProperties = cast[proc(physicalDevice: VkPhysicalDevice, pProperties: ptr VkPhysicalDeviceProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties")) + vkGetPhysicalDeviceQueueFamilyProperties = cast[proc(physicalDevice: VkPhysicalDevice, pQueueFamilyPropertyCount: ptr uint32, pQueueFamilyProperties: ptr VkQueueFamilyProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties")) + vkGetPhysicalDeviceMemoryProperties = cast[proc(physicalDevice: VkPhysicalDevice, pMemoryProperties: ptr VkPhysicalDeviceMemoryProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties")) + vkGetDeviceProcAddr = cast[proc(device: VkDevice, pName: cstring): PFN_vkVoidFunction {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceProcAddr")) + vkCreateDevice = cast[proc(physicalDevice: VkPhysicalDevice, pCreateInfo: ptr VkDeviceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDevice: ptr VkDevice): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDevice")) + vkDestroyDevice = cast[proc(device: VkDevice, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDevice")) + vkEnumerateDeviceExtensionProperties = cast[proc(physicalDevice: VkPhysicalDevice, pLayerName: cstring, pPropertyCount: ptr uint32, pProperties: ptr VkExtensionProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumerateDeviceExtensionProperties")) + vkEnumerateDeviceLayerProperties = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkLayerProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumerateDeviceLayerProperties")) + vkGetDeviceQueue = cast[proc(device: VkDevice, queueFamilyIndex: uint32, queueIndex: uint32, pQueue: ptr VkQueue): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceQueue")) + vkQueueSubmit = cast[proc(queue: VkQueue, submitCount: uint32, pSubmits: ptr VkSubmitInfo, fence: VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueSubmit")) + vkQueueWaitIdle = cast[proc(queue: VkQueue): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueWaitIdle")) + vkDeviceWaitIdle = cast[proc(device: VkDevice): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDeviceWaitIdle")) + vkAllocateMemory = cast[proc(device: VkDevice, pAllocateInfo: ptr VkMemoryAllocateInfo, pAllocator: ptr VkAllocationCallbacks, pMemory: ptr VkDeviceMemory): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAllocateMemory")) + vkFreeMemory = cast[proc(device: VkDevice, memory: VkDeviceMemory, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkFreeMemory")) + vkMapMemory = cast[proc(device: VkDevice, memory: VkDeviceMemory, offset: VkDeviceSize, size: VkDeviceSize, flags: VkMemoryMapFlags, ppData: ptr pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkMapMemory")) + vkUnmapMemory = cast[proc(device: VkDevice, memory: VkDeviceMemory): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkUnmapMemory")) + vkFlushMappedMemoryRanges = cast[proc(device: VkDevice, memoryRangeCount: uint32, pMemoryRanges: ptr VkMappedMemoryRange): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkFlushMappedMemoryRanges")) + vkInvalidateMappedMemoryRanges = cast[proc(device: VkDevice, memoryRangeCount: uint32, pMemoryRanges: ptr VkMappedMemoryRange): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkInvalidateMappedMemoryRanges")) + vkGetDeviceMemoryCommitment = cast[proc(device: VkDevice, memory: VkDeviceMemory, pCommittedMemoryInBytes: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceMemoryCommitment")) + vkBindBufferMemory = cast[proc(device: VkDevice, buffer: VkBuffer, memory: VkDeviceMemory, memoryOffset: VkDeviceSize): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindBufferMemory")) + vkBindImageMemory = cast[proc(device: VkDevice, image: VkImage, memory: VkDeviceMemory, memoryOffset: VkDeviceSize): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindImageMemory")) + vkGetBufferMemoryRequirements = cast[proc(device: VkDevice, buffer: VkBuffer, pMemoryRequirements: ptr VkMemoryRequirements): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferMemoryRequirements")) + vkGetImageMemoryRequirements = cast[proc(device: VkDevice, image: VkImage, pMemoryRequirements: ptr VkMemoryRequirements): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageMemoryRequirements")) + vkGetImageSparseMemoryRequirements = cast[proc(device: VkDevice, image: VkImage, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageSparseMemoryRequirements")) + vkGetPhysicalDeviceSparseImageFormatProperties = cast[proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, samples: VkSampleCountFlagBits, usage: VkImageUsageFlags, tiling: VkImageTiling, pPropertyCount: ptr uint32, pProperties: ptr VkSparseImageFormatProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties")) + vkQueueBindSparse = cast[proc(queue: VkQueue, bindInfoCount: uint32, pBindInfo: ptr VkBindSparseInfo, fence: VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueBindSparse")) + vkCreateFence = cast[proc(device: VkDevice, pCreateInfo: ptr VkFenceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateFence")) + vkDestroyFence = cast[proc(device: VkDevice, fence: VkFence, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyFence")) + vkResetFences = cast[proc(device: VkDevice, fenceCount: uint32, pFences: ptr VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetFences")) + vkGetFenceStatus = cast[proc(device: VkDevice, fence: VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetFenceStatus")) + vkWaitForFences = cast[proc(device: VkDevice, fenceCount: uint32, pFences: ptr VkFence, waitAll: VkBool32, timeout: uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkWaitForFences")) + vkCreateSemaphore = cast[proc(device: VkDevice, pCreateInfo: ptr VkSemaphoreCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSemaphore: ptr VkSemaphore): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateSemaphore")) + vkDestroySemaphore = cast[proc(device: VkDevice, semaphore: VkSemaphore, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroySemaphore")) + vkCreateEvent = cast[proc(device: VkDevice, pCreateInfo: ptr VkEventCreateInfo, pAllocator: ptr VkAllocationCallbacks, pEvent: ptr VkEvent): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateEvent")) + vkDestroyEvent = cast[proc(device: VkDevice, event: VkEvent, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyEvent")) + vkGetEventStatus = cast[proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetEventStatus")) + vkSetEvent = cast[proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetEvent")) + vkResetEvent = cast[proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetEvent")) + vkCreateQueryPool = cast[proc(device: VkDevice, pCreateInfo: ptr VkQueryPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pQueryPool: ptr VkQueryPool): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateQueryPool")) + vkDestroyQueryPool = cast[proc(device: VkDevice, queryPool: VkQueryPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyQueryPool")) + vkGetQueryPoolResults = cast[proc(device: VkDevice, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32, dataSize: csize_t, pData: pointer, stride: VkDeviceSize, flags: VkQueryResultFlags): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetQueryPoolResults")) + vkCreateBuffer = cast[proc(device: VkDevice, pCreateInfo: ptr VkBufferCreateInfo, pAllocator: ptr VkAllocationCallbacks, pBuffer: ptr VkBuffer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateBuffer")) + vkDestroyBuffer = cast[proc(device: VkDevice, buffer: VkBuffer, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyBuffer")) + vkCreateBufferView = cast[proc(device: VkDevice, pCreateInfo: ptr VkBufferViewCreateInfo, pAllocator: ptr VkAllocationCallbacks, pView: ptr VkBufferView): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateBufferView")) + vkDestroyBufferView = cast[proc(device: VkDevice, bufferView: VkBufferView, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyBufferView")) + vkCreateImage = cast[proc(device: VkDevice, pCreateInfo: ptr VkImageCreateInfo, pAllocator: ptr VkAllocationCallbacks, pImage: ptr VkImage): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateImage")) + vkDestroyImage = cast[proc(device: VkDevice, image: VkImage, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyImage")) + vkGetImageSubresourceLayout = cast[proc(device: VkDevice, image: VkImage, pSubresource: ptr VkImageSubresource, pLayout: ptr VkSubresourceLayout): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageSubresourceLayout")) + vkCreateImageView = cast[proc(device: VkDevice, pCreateInfo: ptr VkImageViewCreateInfo, pAllocator: ptr VkAllocationCallbacks, pView: ptr VkImageView): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateImageView")) + vkDestroyImageView = cast[proc(device: VkDevice, imageView: VkImageView, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyImageView")) + vkCreateShaderModule = cast[proc(device: VkDevice, pCreateInfo: ptr VkShaderModuleCreateInfo, pAllocator: ptr VkAllocationCallbacks, pShaderModule: ptr VkShaderModule): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateShaderModule")) + vkDestroyShaderModule = cast[proc(device: VkDevice, shaderModule: VkShaderModule, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyShaderModule")) + vkCreatePipelineCache = cast[proc(device: VkDevice, pCreateInfo: ptr VkPipelineCacheCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelineCache: ptr VkPipelineCache): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreatePipelineCache")) + vkDestroyPipelineCache = cast[proc(device: VkDevice, pipelineCache: VkPipelineCache, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyPipelineCache")) + vkGetPipelineCacheData = cast[proc(device: VkDevice, pipelineCache: VkPipelineCache, pDataSize: ptr csize_t, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPipelineCacheData")) + vkMergePipelineCaches = cast[proc(device: VkDevice, dstCache: VkPipelineCache, srcCacheCount: uint32, pSrcCaches: ptr VkPipelineCache): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkMergePipelineCaches")) + vkCreateGraphicsPipelines = cast[proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkGraphicsPipelineCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateGraphicsPipelines")) + vkCreateComputePipelines = cast[proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkComputePipelineCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateComputePipelines")) + vkDestroyPipeline = cast[proc(device: VkDevice, pipeline: VkPipeline, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyPipeline")) + vkCreatePipelineLayout = cast[proc(device: VkDevice, pCreateInfo: ptr VkPipelineLayoutCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelineLayout: ptr VkPipelineLayout): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreatePipelineLayout")) + vkDestroyPipelineLayout = cast[proc(device: VkDevice, pipelineLayout: VkPipelineLayout, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyPipelineLayout")) + vkCreateSampler = cast[proc(device: VkDevice, pCreateInfo: ptr VkSamplerCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSampler: ptr VkSampler): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateSampler")) + vkDestroySampler = cast[proc(device: VkDevice, sampler: VkSampler, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroySampler")) + vkCreateDescriptorSetLayout = cast[proc(device: VkDevice, pCreateInfo: ptr VkDescriptorSetLayoutCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSetLayout: ptr VkDescriptorSetLayout): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDescriptorSetLayout")) + vkDestroyDescriptorSetLayout = cast[proc(device: VkDevice, descriptorSetLayout: VkDescriptorSetLayout, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDescriptorSetLayout")) + vkCreateDescriptorPool = cast[proc(device: VkDevice, pCreateInfo: ptr VkDescriptorPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDescriptorPool: ptr VkDescriptorPool): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDescriptorPool")) + vkDestroyDescriptorPool = cast[proc(device: VkDevice, descriptorPool: VkDescriptorPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDescriptorPool")) + vkResetDescriptorPool = cast[proc(device: VkDevice, descriptorPool: VkDescriptorPool, flags: VkDescriptorPoolResetFlags): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetDescriptorPool")) + vkAllocateDescriptorSets = cast[proc(device: VkDevice, pAllocateInfo: ptr VkDescriptorSetAllocateInfo, pDescriptorSets: ptr VkDescriptorSet): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAllocateDescriptorSets")) + vkFreeDescriptorSets = cast[proc(device: VkDevice, descriptorPool: VkDescriptorPool, descriptorSetCount: uint32, pDescriptorSets: ptr VkDescriptorSet): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkFreeDescriptorSets")) + vkUpdateDescriptorSets = cast[proc(device: VkDevice, descriptorWriteCount: uint32, pDescriptorWrites: ptr VkWriteDescriptorSet, descriptorCopyCount: uint32, pDescriptorCopies: ptr VkCopyDescriptorSet): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkUpdateDescriptorSets")) + vkCreateFramebuffer = cast[proc(device: VkDevice, pCreateInfo: ptr VkFramebufferCreateInfo, pAllocator: ptr VkAllocationCallbacks, pFramebuffer: ptr VkFramebuffer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateFramebuffer")) + vkDestroyFramebuffer = cast[proc(device: VkDevice, framebuffer: VkFramebuffer, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyFramebuffer")) + vkCreateRenderPass = cast[proc(device: VkDevice, pCreateInfo: ptr VkRenderPassCreateInfo, pAllocator: ptr VkAllocationCallbacks, pRenderPass: ptr VkRenderPass): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateRenderPass")) + vkDestroyRenderPass = cast[proc(device: VkDevice, renderPass: VkRenderPass, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyRenderPass")) + vkGetRenderAreaGranularity = cast[proc(device: VkDevice, renderPass: VkRenderPass, pGranularity: ptr VkExtent2D): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRenderAreaGranularity")) + vkCreateCommandPool = cast[proc(device: VkDevice, pCreateInfo: ptr VkCommandPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pCommandPool: ptr VkCommandPool): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateCommandPool")) + vkDestroyCommandPool = cast[proc(device: VkDevice, commandPool: VkCommandPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyCommandPool")) + vkResetCommandPool = cast[proc(device: VkDevice, commandPool: VkCommandPool, flags: VkCommandPoolResetFlags): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetCommandPool")) + vkAllocateCommandBuffers = cast[proc(device: VkDevice, pAllocateInfo: ptr VkCommandBufferAllocateInfo, pCommandBuffers: ptr VkCommandBuffer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAllocateCommandBuffers")) + vkFreeCommandBuffers = cast[proc(device: VkDevice, commandPool: VkCommandPool, commandBufferCount: uint32, pCommandBuffers: ptr VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkFreeCommandBuffers")) + vkBeginCommandBuffer = cast[proc(commandBuffer: VkCommandBuffer, pBeginInfo: ptr VkCommandBufferBeginInfo): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBeginCommandBuffer")) + vkEndCommandBuffer = cast[proc(commandBuffer: VkCommandBuffer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEndCommandBuffer")) + vkResetCommandBuffer = cast[proc(commandBuffer: VkCommandBuffer, flags: VkCommandBufferResetFlags): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetCommandBuffer")) + vkCmdBindPipeline = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, pipeline: VkPipeline): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindPipeline")) + vkCmdSetViewport = cast[proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewports: ptr VkViewport): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewport")) + vkCmdSetScissor = cast[proc(commandBuffer: VkCommandBuffer, firstScissor: uint32, scissorCount: uint32, pScissors: ptr VkRect2D): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetScissor")) + vkCmdSetLineWidth = cast[proc(commandBuffer: VkCommandBuffer, lineWidth: float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetLineWidth")) + vkCmdSetDepthBias = cast[proc(commandBuffer: VkCommandBuffer, depthBiasConstantFactor: float32, depthBiasClamp: float32, depthBiasSlopeFactor: float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthBias")) + vkCmdSetBlendConstants = cast[proc(commandBuffer: VkCommandBuffer, blendConstants: array[4, float32]): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetBlendConstants")) + vkCmdSetDepthBounds = cast[proc(commandBuffer: VkCommandBuffer, minDepthBounds: float32, maxDepthBounds: float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthBounds")) + vkCmdSetStencilCompareMask = cast[proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, compareMask: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetStencilCompareMask")) + vkCmdSetStencilWriteMask = cast[proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, writeMask: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetStencilWriteMask")) + vkCmdSetStencilReference = cast[proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, reference: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetStencilReference")) + vkCmdBindDescriptorSets = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, firstSet: uint32, descriptorSetCount: uint32, pDescriptorSets: ptr VkDescriptorSet, dynamicOffsetCount: uint32, pDynamicOffsets: ptr uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindDescriptorSets")) + vkCmdBindIndexBuffer = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, indexType: VkIndexType): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindIndexBuffer")) + vkCmdBindVertexBuffers = cast[proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindVertexBuffers")) + vkCmdDraw = cast[proc(commandBuffer: VkCommandBuffer, vertexCount: uint32, instanceCount: uint32, firstVertex: uint32, firstInstance: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDraw")) + vkCmdDrawIndexed = cast[proc(commandBuffer: VkCommandBuffer, indexCount: uint32, instanceCount: uint32, firstIndex: uint32, vertexOffset: int32, firstInstance: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndexed")) + vkCmdDrawIndirect = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndirect")) + vkCmdDrawIndexedIndirect = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirect")) + vkCmdDispatch = cast[proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDispatch")) + vkCmdDispatchIndirect = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDispatchIndirect")) + vkCmdCopyBuffer = cast[proc(commandBuffer: VkCommandBuffer, srcBuffer: VkBuffer, dstBuffer: VkBuffer, regionCount: uint32, pRegions: ptr VkBufferCopy): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyBuffer")) + vkCmdCopyImage = cast[proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageCopy): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyImage")) + vkCmdBlitImage = cast[proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageBlit, filter: VkFilter): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBlitImage")) + vkCmdCopyBufferToImage = cast[proc(commandBuffer: VkCommandBuffer, srcBuffer: VkBuffer, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkBufferImageCopy): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyBufferToImage")) + vkCmdCopyImageToBuffer = cast[proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstBuffer: VkBuffer, regionCount: uint32, pRegions: ptr VkBufferImageCopy): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyImageToBuffer")) + vkCmdUpdateBuffer = cast[proc(commandBuffer: VkCommandBuffer, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, dataSize: VkDeviceSize, pData: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdUpdateBuffer")) + vkCmdFillBuffer = cast[proc(commandBuffer: VkCommandBuffer, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, size: VkDeviceSize, data: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdFillBuffer")) + vkCmdClearColorImage = cast[proc(commandBuffer: VkCommandBuffer, image: VkImage, imageLayout: VkImageLayout, pColor: ptr VkClearColorValue, rangeCount: uint32, pRanges: ptr VkImageSubresourceRange): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdClearColorImage")) + vkCmdClearDepthStencilImage = cast[proc(commandBuffer: VkCommandBuffer, image: VkImage, imageLayout: VkImageLayout, pDepthStencil: ptr VkClearDepthStencilValue, rangeCount: uint32, pRanges: ptr VkImageSubresourceRange): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdClearDepthStencilImage")) + vkCmdClearAttachments = cast[proc(commandBuffer: VkCommandBuffer, attachmentCount: uint32, pAttachments: ptr VkClearAttachment, rectCount: uint32, pRects: ptr VkClearRect): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdClearAttachments")) + vkCmdResolveImage = cast[proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageResolve): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdResolveImage")) + vkCmdSetEvent = cast[proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetEvent")) + vkCmdResetEvent = cast[proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdResetEvent")) + vkCmdWaitEvents = cast[proc(commandBuffer: VkCommandBuffer, eventCount: uint32, pEvents: ptr VkEvent, srcStageMask: VkPipelineStageFlags, dstStageMask: VkPipelineStageFlags, memoryBarrierCount: uint32, pMemoryBarriers: ptr VkMemoryBarrier, bufferMemoryBarrierCount: uint32, pBufferMemoryBarriers: ptr VkBufferMemoryBarrier, imageMemoryBarrierCount: uint32, pImageMemoryBarriers: ptr VkImageMemoryBarrier): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWaitEvents")) + vkCmdPipelineBarrier = cast[proc(commandBuffer: VkCommandBuffer, srcStageMask: VkPipelineStageFlags, dstStageMask: VkPipelineStageFlags, dependencyFlags: VkDependencyFlags, memoryBarrierCount: uint32, pMemoryBarriers: ptr VkMemoryBarrier, bufferMemoryBarrierCount: uint32, pBufferMemoryBarriers: ptr VkBufferMemoryBarrier, imageMemoryBarrierCount: uint32, pImageMemoryBarriers: ptr VkImageMemoryBarrier): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPipelineBarrier")) + vkCmdBeginQuery = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, flags: VkQueryControlFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginQuery")) + vkCmdEndQuery = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndQuery")) + vkCmdResetQueryPool = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdResetQueryPool")) + vkCmdWriteTimestamp = cast[proc(commandBuffer: VkCommandBuffer, pipelineStage: VkPipelineStageFlagBits, queryPool: VkQueryPool, query: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteTimestamp")) + vkCmdCopyQueryPoolResults = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, stride: VkDeviceSize, flags: VkQueryResultFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyQueryPoolResults")) + vkCmdPushConstants = cast[proc(commandBuffer: VkCommandBuffer, layout: VkPipelineLayout, stageFlags: VkShaderStageFlags, offset: uint32, size: uint32, pValues: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPushConstants")) + vkCmdBeginRenderPass = cast[proc(commandBuffer: VkCommandBuffer, pRenderPassBegin: ptr VkRenderPassBeginInfo, contents: VkSubpassContents): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginRenderPass")) + vkCmdNextSubpass = cast[proc(commandBuffer: VkCommandBuffer, contents: VkSubpassContents): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdNextSubpass")) + vkCmdEndRenderPass = cast[proc(commandBuffer: VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndRenderPass")) + vkCmdExecuteCommands = cast[proc(commandBuffer: VkCommandBuffer, commandBufferCount: uint32, pCommandBuffers: ptr VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdExecuteCommands")) + +# feature VK_VERSION_1_1 +var + vkEnumerateInstanceVersion*: proc(pApiVersion: ptr uint32): VkResult {.stdcall.} + vkBindBufferMemory2*: proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindBufferMemoryInfo): VkResult {.stdcall.} + vkBindImageMemory2*: proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindImageMemoryInfo): VkResult {.stdcall.} + vkGetDeviceGroupPeerMemoryFeatures*: proc(device: VkDevice, heapIndex: uint32, localDeviceIndex: uint32, remoteDeviceIndex: uint32, pPeerMemoryFeatures: ptr VkPeerMemoryFeatureFlags): void {.stdcall.} + vkCmdSetDeviceMask*: proc(commandBuffer: VkCommandBuffer, deviceMask: uint32): void {.stdcall.} + vkCmdDispatchBase*: proc(commandBuffer: VkCommandBuffer, baseGroupX: uint32, baseGroupY: uint32, baseGroupZ: uint32, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.} + vkEnumeratePhysicalDeviceGroups*: proc(instance: VkInstance, pPhysicalDeviceGroupCount: ptr uint32, pPhysicalDeviceGroupProperties: ptr VkPhysicalDeviceGroupProperties): VkResult {.stdcall.} + vkGetImageMemoryRequirements2*: proc(device: VkDevice, pInfo: ptr VkImageMemoryRequirementsInfo2, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.} + vkGetBufferMemoryRequirements2*: proc(device: VkDevice, pInfo: ptr VkBufferMemoryRequirementsInfo2, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.} + vkGetImageSparseMemoryRequirements2*: proc(device: VkDevice, pInfo: ptr VkImageSparseMemoryRequirementsInfo2, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements2): void {.stdcall.} + vkGetPhysicalDeviceFeatures2*: proc(physicalDevice: VkPhysicalDevice, pFeatures: ptr VkPhysicalDeviceFeatures2): void {.stdcall.} + vkGetPhysicalDeviceProperties2*: proc(physicalDevice: VkPhysicalDevice, pProperties: ptr VkPhysicalDeviceProperties2): void {.stdcall.} + vkGetPhysicalDeviceFormatProperties2*: proc(physicalDevice: VkPhysicalDevice, format: VkFormat, pFormatProperties: ptr VkFormatProperties2): void {.stdcall.} + vkGetPhysicalDeviceImageFormatProperties2*: proc(physicalDevice: VkPhysicalDevice, pImageFormatInfo: ptr VkPhysicalDeviceImageFormatInfo2, pImageFormatProperties: ptr VkImageFormatProperties2): VkResult {.stdcall.} + vkGetPhysicalDeviceQueueFamilyProperties2*: proc(physicalDevice: VkPhysicalDevice, pQueueFamilyPropertyCount: ptr uint32, pQueueFamilyProperties: ptr VkQueueFamilyProperties2): void {.stdcall.} + vkGetPhysicalDeviceMemoryProperties2*: proc(physicalDevice: VkPhysicalDevice, pMemoryProperties: ptr VkPhysicalDeviceMemoryProperties2): void {.stdcall.} + vkGetPhysicalDeviceSparseImageFormatProperties2*: proc(physicalDevice: VkPhysicalDevice, pFormatInfo: ptr VkPhysicalDeviceSparseImageFormatInfo2, pPropertyCount: ptr uint32, pProperties: ptr VkSparseImageFormatProperties2): void {.stdcall.} + vkTrimCommandPool*: proc(device: VkDevice, commandPool: VkCommandPool, flags: VkCommandPoolTrimFlags): void {.stdcall.} + vkGetDeviceQueue2*: proc(device: VkDevice, pQueueInfo: ptr VkDeviceQueueInfo2, pQueue: ptr VkQueue): void {.stdcall.} + vkCreateSamplerYcbcrConversion*: proc(device: VkDevice, pCreateInfo: ptr VkSamplerYcbcrConversionCreateInfo, pAllocator: ptr VkAllocationCallbacks, pYcbcrConversion: ptr VkSamplerYcbcrConversion): VkResult {.stdcall.} + vkDestroySamplerYcbcrConversion*: proc(device: VkDevice, ycbcrConversion: VkSamplerYcbcrConversion, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCreateDescriptorUpdateTemplate*: proc(device: VkDevice, pCreateInfo: ptr VkDescriptorUpdateTemplateCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDescriptorUpdateTemplate: ptr VkDescriptorUpdateTemplate): VkResult {.stdcall.} + vkDestroyDescriptorUpdateTemplate*: proc(device: VkDevice, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkUpdateDescriptorSetWithTemplate*: proc(device: VkDevice, descriptorSet: VkDescriptorSet, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, pData: pointer): void {.stdcall.} + vkGetPhysicalDeviceExternalBufferProperties*: proc(physicalDevice: VkPhysicalDevice, pExternalBufferInfo: ptr VkPhysicalDeviceExternalBufferInfo, pExternalBufferProperties: ptr VkExternalBufferProperties): void {.stdcall.} + vkGetPhysicalDeviceExternalFenceProperties*: proc(physicalDevice: VkPhysicalDevice, pExternalFenceInfo: ptr VkPhysicalDeviceExternalFenceInfo, pExternalFenceProperties: ptr VkExternalFenceProperties): void {.stdcall.} + vkGetPhysicalDeviceExternalSemaphoreProperties*: proc(physicalDevice: VkPhysicalDevice, pExternalSemaphoreInfo: ptr VkPhysicalDeviceExternalSemaphoreInfo, pExternalSemaphoreProperties: ptr VkExternalSemaphoreProperties): void {.stdcall.} + vkGetDescriptorSetLayoutSupport*: proc(device: VkDevice, pCreateInfo: ptr VkDescriptorSetLayoutCreateInfo, pSupport: ptr VkDescriptorSetLayoutSupport): void {.stdcall.} +proc loadVK_VERSION_1_1*(instance: VkInstance) = + vkBindBufferMemory2 = cast[proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindBufferMemoryInfo): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindBufferMemory2")) + vkBindImageMemory2 = cast[proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindImageMemoryInfo): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindImageMemory2")) + vkGetDeviceGroupPeerMemoryFeatures = cast[proc(device: VkDevice, heapIndex: uint32, localDeviceIndex: uint32, remoteDeviceIndex: uint32, pPeerMemoryFeatures: ptr VkPeerMemoryFeatureFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceGroupPeerMemoryFeatures")) + vkCmdSetDeviceMask = cast[proc(commandBuffer: VkCommandBuffer, deviceMask: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDeviceMask")) + vkCmdDispatchBase = cast[proc(commandBuffer: VkCommandBuffer, baseGroupX: uint32, baseGroupY: uint32, baseGroupZ: uint32, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDispatchBase")) + vkEnumeratePhysicalDeviceGroups = cast[proc(instance: VkInstance, pPhysicalDeviceGroupCount: ptr uint32, pPhysicalDeviceGroupProperties: ptr VkPhysicalDeviceGroupProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroups")) + vkGetImageMemoryRequirements2 = cast[proc(device: VkDevice, pInfo: ptr VkImageMemoryRequirementsInfo2, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageMemoryRequirements2")) + vkGetBufferMemoryRequirements2 = cast[proc(device: VkDevice, pInfo: ptr VkBufferMemoryRequirementsInfo2, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferMemoryRequirements2")) + vkGetImageSparseMemoryRequirements2 = cast[proc(device: VkDevice, pInfo: ptr VkImageSparseMemoryRequirementsInfo2, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageSparseMemoryRequirements2")) + vkGetPhysicalDeviceFeatures2 = cast[proc(physicalDevice: VkPhysicalDevice, pFeatures: ptr VkPhysicalDeviceFeatures2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2")) + vkGetPhysicalDeviceProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, pProperties: ptr VkPhysicalDeviceProperties2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2")) + vkGetPhysicalDeviceFormatProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, format: VkFormat, pFormatProperties: ptr VkFormatProperties2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2")) + vkGetPhysicalDeviceImageFormatProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, pImageFormatInfo: ptr VkPhysicalDeviceImageFormatInfo2, pImageFormatProperties: ptr VkImageFormatProperties2): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2")) + vkGetPhysicalDeviceQueueFamilyProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, pQueueFamilyPropertyCount: ptr uint32, pQueueFamilyProperties: ptr VkQueueFamilyProperties2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2")) + vkGetPhysicalDeviceMemoryProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, pMemoryProperties: ptr VkPhysicalDeviceMemoryProperties2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2")) + vkGetPhysicalDeviceSparseImageFormatProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, pFormatInfo: ptr VkPhysicalDeviceSparseImageFormatInfo2, pPropertyCount: ptr uint32, pProperties: ptr VkSparseImageFormatProperties2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2")) + vkTrimCommandPool = cast[proc(device: VkDevice, commandPool: VkCommandPool, flags: VkCommandPoolTrimFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkTrimCommandPool")) + vkGetDeviceQueue2 = cast[proc(device: VkDevice, pQueueInfo: ptr VkDeviceQueueInfo2, pQueue: ptr VkQueue): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceQueue2")) + vkCreateSamplerYcbcrConversion = cast[proc(device: VkDevice, pCreateInfo: ptr VkSamplerYcbcrConversionCreateInfo, pAllocator: ptr VkAllocationCallbacks, pYcbcrConversion: ptr VkSamplerYcbcrConversion): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateSamplerYcbcrConversion")) + vkDestroySamplerYcbcrConversion = cast[proc(device: VkDevice, ycbcrConversion: VkSamplerYcbcrConversion, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroySamplerYcbcrConversion")) + vkCreateDescriptorUpdateTemplate = cast[proc(device: VkDevice, pCreateInfo: ptr VkDescriptorUpdateTemplateCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDescriptorUpdateTemplate: ptr VkDescriptorUpdateTemplate): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDescriptorUpdateTemplate")) + vkDestroyDescriptorUpdateTemplate = cast[proc(device: VkDevice, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDescriptorUpdateTemplate")) + vkUpdateDescriptorSetWithTemplate = cast[proc(device: VkDevice, descriptorSet: VkDescriptorSet, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, pData: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkUpdateDescriptorSetWithTemplate")) + vkGetPhysicalDeviceExternalBufferProperties = cast[proc(physicalDevice: VkPhysicalDevice, pExternalBufferInfo: ptr VkPhysicalDeviceExternalBufferInfo, pExternalBufferProperties: ptr VkExternalBufferProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferProperties")) + vkGetPhysicalDeviceExternalFenceProperties = cast[proc(physicalDevice: VkPhysicalDevice, pExternalFenceInfo: ptr VkPhysicalDeviceExternalFenceInfo, pExternalFenceProperties: ptr VkExternalFenceProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFenceProperties")) + vkGetPhysicalDeviceExternalSemaphoreProperties = cast[proc(physicalDevice: VkPhysicalDevice, pExternalSemaphoreInfo: ptr VkPhysicalDeviceExternalSemaphoreInfo, pExternalSemaphoreProperties: ptr VkExternalSemaphoreProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphoreProperties")) + vkGetDescriptorSetLayoutSupport = cast[proc(device: VkDevice, pCreateInfo: ptr VkDescriptorSetLayoutCreateInfo, pSupport: ptr VkDescriptorSetLayoutSupport): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorSetLayoutSupport")) + +# feature VK_VERSION_1_2 +var + vkCmdDrawIndirectCount*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.} + vkCmdDrawIndexedIndirectCount*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.} + vkCreateRenderPass2*: proc(device: VkDevice, pCreateInfo: ptr VkRenderPassCreateInfo2, pAllocator: ptr VkAllocationCallbacks, pRenderPass: ptr VkRenderPass): VkResult {.stdcall.} + vkCmdBeginRenderPass2*: proc(commandBuffer: VkCommandBuffer, pRenderPassBegin: ptr VkRenderPassBeginInfo, pSubpassBeginInfo: ptr VkSubpassBeginInfo): void {.stdcall.} + vkCmdNextSubpass2*: proc(commandBuffer: VkCommandBuffer, pSubpassBeginInfo: ptr VkSubpassBeginInfo, pSubpassEndInfo: ptr VkSubpassEndInfo): void {.stdcall.} + vkCmdEndRenderPass2*: proc(commandBuffer: VkCommandBuffer, pSubpassEndInfo: ptr VkSubpassEndInfo): void {.stdcall.} + vkResetQueryPool*: proc(device: VkDevice, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32): void {.stdcall.} + vkGetSemaphoreCounterValue*: proc(device: VkDevice, semaphore: VkSemaphore, pValue: ptr uint64): VkResult {.stdcall.} + vkWaitSemaphores*: proc(device: VkDevice, pWaitInfo: ptr VkSemaphoreWaitInfo, timeout: uint64): VkResult {.stdcall.} + vkSignalSemaphore*: proc(device: VkDevice, pSignalInfo: ptr VkSemaphoreSignalInfo): VkResult {.stdcall.} + vkGetBufferDeviceAddress*: proc(device: VkDevice, pInfo: ptr VkBufferDeviceAddressInfo): VkDeviceAddress {.stdcall.} + vkGetBufferOpaqueCaptureAddress*: proc(device: VkDevice, pInfo: ptr VkBufferDeviceAddressInfo): uint64 {.stdcall.} + vkGetDeviceMemoryOpaqueCaptureAddress*: proc(device: VkDevice, pInfo: ptr VkDeviceMemoryOpaqueCaptureAddressInfo): uint64 {.stdcall.} +proc loadVK_VERSION_1_2*(instance: VkInstance) = + vkCmdDrawIndirectCount = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndirectCount")) + vkCmdDrawIndexedIndirectCount = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirectCount")) + vkCreateRenderPass2 = cast[proc(device: VkDevice, pCreateInfo: ptr VkRenderPassCreateInfo2, pAllocator: ptr VkAllocationCallbacks, pRenderPass: ptr VkRenderPass): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateRenderPass2")) + vkCmdBeginRenderPass2 = cast[proc(commandBuffer: VkCommandBuffer, pRenderPassBegin: ptr VkRenderPassBeginInfo, pSubpassBeginInfo: ptr VkSubpassBeginInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginRenderPass2")) + vkCmdNextSubpass2 = cast[proc(commandBuffer: VkCommandBuffer, pSubpassBeginInfo: ptr VkSubpassBeginInfo, pSubpassEndInfo: ptr VkSubpassEndInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdNextSubpass2")) + vkCmdEndRenderPass2 = cast[proc(commandBuffer: VkCommandBuffer, pSubpassEndInfo: ptr VkSubpassEndInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndRenderPass2")) + vkResetQueryPool = cast[proc(device: VkDevice, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetQueryPool")) + vkGetSemaphoreCounterValue = cast[proc(device: VkDevice, semaphore: VkSemaphore, pValue: ptr uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSemaphoreCounterValue")) + vkWaitSemaphores = cast[proc(device: VkDevice, pWaitInfo: ptr VkSemaphoreWaitInfo, timeout: uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkWaitSemaphores")) + vkSignalSemaphore = cast[proc(device: VkDevice, pSignalInfo: ptr VkSemaphoreSignalInfo): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSignalSemaphore")) + vkGetBufferDeviceAddress = cast[proc(device: VkDevice, pInfo: ptr VkBufferDeviceAddressInfo): VkDeviceAddress {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferDeviceAddress")) + vkGetBufferOpaqueCaptureAddress = cast[proc(device: VkDevice, pInfo: ptr VkBufferDeviceAddressInfo): uint64 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferOpaqueCaptureAddress")) + vkGetDeviceMemoryOpaqueCaptureAddress = cast[proc(device: VkDevice, pInfo: ptr VkDeviceMemoryOpaqueCaptureAddressInfo): uint64 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceMemoryOpaqueCaptureAddress")) + +# feature VK_VERSION_1_3 +var + vkGetPhysicalDeviceToolProperties*: proc(physicalDevice: VkPhysicalDevice, pToolCount: ptr uint32, pToolProperties: ptr VkPhysicalDeviceToolProperties): VkResult {.stdcall.} + vkCreatePrivateDataSlot*: proc(device: VkDevice, pCreateInfo: ptr VkPrivateDataSlotCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPrivateDataSlot: ptr VkPrivateDataSlot): VkResult {.stdcall.} + vkDestroyPrivateDataSlot*: proc(device: VkDevice, privateDataSlot: VkPrivateDataSlot, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkSetPrivateData*: proc(device: VkDevice, objectType: VkObjectType, objectHandle: uint64, privateDataSlot: VkPrivateDataSlot, data: uint64): VkResult {.stdcall.} + vkGetPrivateData*: proc(device: VkDevice, objectType: VkObjectType, objectHandle: uint64, privateDataSlot: VkPrivateDataSlot, pData: ptr uint64): void {.stdcall.} + vkCmdSetEvent2*: proc(commandBuffer: VkCommandBuffer, event: VkEvent, pDependencyInfo: ptr VkDependencyInfo): void {.stdcall.} + vkCmdResetEvent2*: proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags2): void {.stdcall.} + vkCmdWaitEvents2*: proc(commandBuffer: VkCommandBuffer, eventCount: uint32, pEvents: ptr VkEvent, pDependencyInfos: ptr VkDependencyInfo): void {.stdcall.} + vkCmdPipelineBarrier2*: proc(commandBuffer: VkCommandBuffer, pDependencyInfo: ptr VkDependencyInfo): void {.stdcall.} + vkCmdWriteTimestamp2*: proc(commandBuffer: VkCommandBuffer, stage: VkPipelineStageFlags2, queryPool: VkQueryPool, query: uint32): void {.stdcall.} + vkQueueSubmit2*: proc(queue: VkQueue, submitCount: uint32, pSubmits: ptr VkSubmitInfo2, fence: VkFence): VkResult {.stdcall.} + vkCmdCopyBuffer2*: proc(commandBuffer: VkCommandBuffer, pCopyBufferInfo: ptr VkCopyBufferInfo2): void {.stdcall.} + vkCmdCopyImage2*: proc(commandBuffer: VkCommandBuffer, pCopyImageInfo: ptr VkCopyImageInfo2): void {.stdcall.} + vkCmdCopyBufferToImage2*: proc(commandBuffer: VkCommandBuffer, pCopyBufferToImageInfo: ptr VkCopyBufferToImageInfo2): void {.stdcall.} + vkCmdCopyImageToBuffer2*: proc(commandBuffer: VkCommandBuffer, pCopyImageToBufferInfo: ptr VkCopyImageToBufferInfo2): void {.stdcall.} + vkCmdBlitImage2*: proc(commandBuffer: VkCommandBuffer, pBlitImageInfo: ptr VkBlitImageInfo2): void {.stdcall.} + vkCmdResolveImage2*: proc(commandBuffer: VkCommandBuffer, pResolveImageInfo: ptr VkResolveImageInfo2): void {.stdcall.} + vkCmdBeginRendering*: proc(commandBuffer: VkCommandBuffer, pRenderingInfo: ptr VkRenderingInfo): void {.stdcall.} + vkCmdEndRendering*: proc(commandBuffer: VkCommandBuffer): void {.stdcall.} + vkCmdSetCullMode*: proc(commandBuffer: VkCommandBuffer, cullMode: VkCullModeFlags): void {.stdcall.} + vkCmdSetFrontFace*: proc(commandBuffer: VkCommandBuffer, frontFace: VkFrontFace): void {.stdcall.} + vkCmdSetPrimitiveTopology*: proc(commandBuffer: VkCommandBuffer, primitiveTopology: VkPrimitiveTopology): void {.stdcall.} + vkCmdSetViewportWithCount*: proc(commandBuffer: VkCommandBuffer, viewportCount: uint32, pViewports: ptr VkViewport): void {.stdcall.} + vkCmdSetScissorWithCount*: proc(commandBuffer: VkCommandBuffer, scissorCount: uint32, pScissors: ptr VkRect2D): void {.stdcall.} + vkCmdBindVertexBuffers2*: proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize, pSizes: ptr VkDeviceSize, pStrides: ptr VkDeviceSize): void {.stdcall.} + vkCmdSetDepthTestEnable*: proc(commandBuffer: VkCommandBuffer, depthTestEnable: VkBool32): void {.stdcall.} + vkCmdSetDepthWriteEnable*: proc(commandBuffer: VkCommandBuffer, depthWriteEnable: VkBool32): void {.stdcall.} + vkCmdSetDepthCompareOp*: proc(commandBuffer: VkCommandBuffer, depthCompareOp: VkCompareOp): void {.stdcall.} + vkCmdSetDepthBoundsTestEnable*: proc(commandBuffer: VkCommandBuffer, depthBoundsTestEnable: VkBool32): void {.stdcall.} + vkCmdSetStencilTestEnable*: proc(commandBuffer: VkCommandBuffer, stencilTestEnable: VkBool32): void {.stdcall.} + vkCmdSetStencilOp*: proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, failOp: VkStencilOp, passOp: VkStencilOp, depthFailOp: VkStencilOp, compareOp: VkCompareOp): void {.stdcall.} + vkCmdSetRasterizerDiscardEnable*: proc(commandBuffer: VkCommandBuffer, rasterizerDiscardEnable: VkBool32): void {.stdcall.} + vkCmdSetDepthBiasEnable*: proc(commandBuffer: VkCommandBuffer, depthBiasEnable: VkBool32): void {.stdcall.} + vkCmdSetPrimitiveRestartEnable*: proc(commandBuffer: VkCommandBuffer, primitiveRestartEnable: VkBool32): void {.stdcall.} + vkGetDeviceBufferMemoryRequirements*: proc(device: VkDevice, pInfo: ptr VkDeviceBufferMemoryRequirements, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.} + vkGetDeviceImageMemoryRequirements*: proc(device: VkDevice, pInfo: ptr VkDeviceImageMemoryRequirements, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.} + vkGetDeviceImageSparseMemoryRequirements*: proc(device: VkDevice, pInfo: ptr VkDeviceImageMemoryRequirements, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements2): void {.stdcall.} +proc loadVK_VERSION_1_3*(instance: VkInstance) = + vkGetPhysicalDeviceToolProperties = cast[proc(physicalDevice: VkPhysicalDevice, pToolCount: ptr uint32, pToolProperties: ptr VkPhysicalDeviceToolProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceToolProperties")) + vkCreatePrivateDataSlot = cast[proc(device: VkDevice, pCreateInfo: ptr VkPrivateDataSlotCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPrivateDataSlot: ptr VkPrivateDataSlot): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreatePrivateDataSlot")) + vkDestroyPrivateDataSlot = cast[proc(device: VkDevice, privateDataSlot: VkPrivateDataSlot, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyPrivateDataSlot")) + vkSetPrivateData = cast[proc(device: VkDevice, objectType: VkObjectType, objectHandle: uint64, privateDataSlot: VkPrivateDataSlot, data: uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetPrivateData")) + vkGetPrivateData = cast[proc(device: VkDevice, objectType: VkObjectType, objectHandle: uint64, privateDataSlot: VkPrivateDataSlot, pData: ptr uint64): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPrivateData")) + vkCmdSetEvent2 = cast[proc(commandBuffer: VkCommandBuffer, event: VkEvent, pDependencyInfo: ptr VkDependencyInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetEvent2")) + vkCmdResetEvent2 = cast[proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdResetEvent2")) + vkCmdWaitEvents2 = cast[proc(commandBuffer: VkCommandBuffer, eventCount: uint32, pEvents: ptr VkEvent, pDependencyInfos: ptr VkDependencyInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWaitEvents2")) + vkCmdPipelineBarrier2 = cast[proc(commandBuffer: VkCommandBuffer, pDependencyInfo: ptr VkDependencyInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPipelineBarrier2")) + vkCmdWriteTimestamp2 = cast[proc(commandBuffer: VkCommandBuffer, stage: VkPipelineStageFlags2, queryPool: VkQueryPool, query: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteTimestamp2")) + vkQueueSubmit2 = cast[proc(queue: VkQueue, submitCount: uint32, pSubmits: ptr VkSubmitInfo2, fence: VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueSubmit2")) + vkCmdCopyBuffer2 = cast[proc(commandBuffer: VkCommandBuffer, pCopyBufferInfo: ptr VkCopyBufferInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyBuffer2")) + vkCmdCopyImage2 = cast[proc(commandBuffer: VkCommandBuffer, pCopyImageInfo: ptr VkCopyImageInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyImage2")) + vkCmdCopyBufferToImage2 = cast[proc(commandBuffer: VkCommandBuffer, pCopyBufferToImageInfo: ptr VkCopyBufferToImageInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyBufferToImage2")) + vkCmdCopyImageToBuffer2 = cast[proc(commandBuffer: VkCommandBuffer, pCopyImageToBufferInfo: ptr VkCopyImageToBufferInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyImageToBuffer2")) + vkCmdBlitImage2 = cast[proc(commandBuffer: VkCommandBuffer, pBlitImageInfo: ptr VkBlitImageInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBlitImage2")) + vkCmdResolveImage2 = cast[proc(commandBuffer: VkCommandBuffer, pResolveImageInfo: ptr VkResolveImageInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdResolveImage2")) + vkCmdBeginRendering = cast[proc(commandBuffer: VkCommandBuffer, pRenderingInfo: ptr VkRenderingInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginRendering")) + vkCmdEndRendering = cast[proc(commandBuffer: VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndRendering")) + vkCmdSetCullMode = cast[proc(commandBuffer: VkCommandBuffer, cullMode: VkCullModeFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCullMode")) + vkCmdSetFrontFace = cast[proc(commandBuffer: VkCommandBuffer, frontFace: VkFrontFace): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetFrontFace")) + vkCmdSetPrimitiveTopology = cast[proc(commandBuffer: VkCommandBuffer, primitiveTopology: VkPrimitiveTopology): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPrimitiveTopology")) + vkCmdSetViewportWithCount = cast[proc(commandBuffer: VkCommandBuffer, viewportCount: uint32, pViewports: ptr VkViewport): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewportWithCount")) + vkCmdSetScissorWithCount = cast[proc(commandBuffer: VkCommandBuffer, scissorCount: uint32, pScissors: ptr VkRect2D): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetScissorWithCount")) + vkCmdBindVertexBuffers2 = cast[proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize, pSizes: ptr VkDeviceSize, pStrides: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindVertexBuffers2")) + vkCmdSetDepthTestEnable = cast[proc(commandBuffer: VkCommandBuffer, depthTestEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthTestEnable")) + vkCmdSetDepthWriteEnable = cast[proc(commandBuffer: VkCommandBuffer, depthWriteEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthWriteEnable")) + vkCmdSetDepthCompareOp = cast[proc(commandBuffer: VkCommandBuffer, depthCompareOp: VkCompareOp): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthCompareOp")) + vkCmdSetDepthBoundsTestEnable = cast[proc(commandBuffer: VkCommandBuffer, depthBoundsTestEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthBoundsTestEnable")) + vkCmdSetStencilTestEnable = cast[proc(commandBuffer: VkCommandBuffer, stencilTestEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetStencilTestEnable")) + vkCmdSetStencilOp = cast[proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, failOp: VkStencilOp, passOp: VkStencilOp, depthFailOp: VkStencilOp, compareOp: VkCompareOp): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetStencilOp")) + vkCmdSetRasterizerDiscardEnable = cast[proc(commandBuffer: VkCommandBuffer, rasterizerDiscardEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetRasterizerDiscardEnable")) + vkCmdSetDepthBiasEnable = cast[proc(commandBuffer: VkCommandBuffer, depthBiasEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthBiasEnable")) + vkCmdSetPrimitiveRestartEnable = cast[proc(commandBuffer: VkCommandBuffer, primitiveRestartEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPrimitiveRestartEnable")) + vkGetDeviceBufferMemoryRequirements = cast[proc(device: VkDevice, pInfo: ptr VkDeviceBufferMemoryRequirements, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceBufferMemoryRequirements")) + vkGetDeviceImageMemoryRequirements = cast[proc(device: VkDevice, pInfo: ptr VkDeviceImageMemoryRequirements, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceImageMemoryRequirements")) + vkGetDeviceImageSparseMemoryRequirements = cast[proc(device: VkDevice, pInfo: ptr VkDeviceImageMemoryRequirements, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceImageSparseMemoryRequirements")) + + +proc loadVulkan*(instance: VkInstance) = + loadVK_VERSION_1_0(instance) + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_2(instance) + loadVK_VERSION_1_3(instance) + +proc loadVK_NV_geometry_shader_passthrough*(instance: VkInstance) = + discard + +proc loadVK_EXT_rasterization_order_attachment_access*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_IMG_format_pvrtc*(instance: VkInstance) = + discard + +proc loadVK_AMD_shader_fragment_mask*(instance: VkInstance) = + discard + +proc loadVK_EXT_primitive_topology_list_restart*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_KHR_global_priority*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_QCOM_image_processing*(instance: VkInstance) = + loadVK_VERSION_1_3(instance) + +# extension VK_AMD_shader_info +var + vkGetShaderInfoAMD*: proc(device: VkDevice, pipeline: VkPipeline, shaderStage: VkShaderStageFlagBits, infoType: VkShaderInfoTypeAMD, pInfoSize: ptr csize_t, pInfo: pointer): VkResult {.stdcall.} +proc loadVK_AMD_shader_info*(instance: VkInstance) = + vkGetShaderInfoAMD = cast[proc(device: VkDevice, pipeline: VkPipeline, shaderStage: VkShaderStageFlagBits, infoType: VkShaderInfoTypeAMD, pInfoSize: ptr csize_t, pInfo: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetShaderInfoAMD")) + +proc loadVK_AMD_gpu_shader_int16*(instance: VkInstance) = + discard + +proc loadVK_EXT_pipeline_robustness*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_EXT_sample_locations +var + vkCmdSetSampleLocationsEXT*: proc(commandBuffer: VkCommandBuffer, pSampleLocationsInfo: ptr VkSampleLocationsInfoEXT): void {.stdcall.} + vkGetPhysicalDeviceMultisamplePropertiesEXT*: proc(physicalDevice: VkPhysicalDevice, samples: VkSampleCountFlagBits, pMultisampleProperties: ptr VkMultisamplePropertiesEXT): void {.stdcall.} +proc loadVK_EXT_sample_locations*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdSetSampleLocationsEXT = cast[proc(commandBuffer: VkCommandBuffer, pSampleLocationsInfo: ptr VkSampleLocationsInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetSampleLocationsEXT")) + vkGetPhysicalDeviceMultisamplePropertiesEXT = cast[proc(physicalDevice: VkPhysicalDevice, samples: VkSampleCountFlagBits, pMultisampleProperties: ptr VkMultisamplePropertiesEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMultisamplePropertiesEXT")) + +# extension VK_EXT_descriptor_buffer +var + vkGetDescriptorSetLayoutSizeEXT*: proc(device: VkDevice, layout: VkDescriptorSetLayout, pLayoutSizeInBytes: ptr VkDeviceSize): void {.stdcall.} + vkGetDescriptorSetLayoutBindingOffsetEXT*: proc(device: VkDevice, layout: VkDescriptorSetLayout, binding: uint32, pOffset: ptr VkDeviceSize): void {.stdcall.} + vkGetDescriptorEXT*: proc(device: VkDevice, pDescriptorInfo: ptr VkDescriptorGetInfoEXT, dataSize: csize_t, pDescriptor: pointer): void {.stdcall.} + vkCmdBindDescriptorBuffersEXT*: proc(commandBuffer: VkCommandBuffer, bufferCount: uint32, pBindingInfos: ptr VkDescriptorBufferBindingInfoEXT): void {.stdcall.} + vkCmdSetDescriptorBufferOffsetsEXT*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, firstSet: uint32, setCount: uint32, pBufferIndices: ptr uint32, pOffsets: ptr VkDeviceSize): void {.stdcall.} + vkCmdBindDescriptorBufferEmbeddedSamplersEXT*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, set: uint32): void {.stdcall.} + vkGetBufferOpaqueCaptureDescriptorDataEXT*: proc(device: VkDevice, pInfo: ptr VkBufferCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.} + vkGetImageOpaqueCaptureDescriptorDataEXT*: proc(device: VkDevice, pInfo: ptr VkImageCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.} + vkGetImageViewOpaqueCaptureDescriptorDataEXT*: proc(device: VkDevice, pInfo: ptr VkImageViewCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.} + vkGetSamplerOpaqueCaptureDescriptorDataEXT*: proc(device: VkDevice, pInfo: ptr VkSamplerCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.} + vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT*: proc(device: VkDevice, pInfo: ptr VkAccelerationStructureCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.} +proc loadVK_EXT_descriptor_buffer*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_2(instance) + loadVK_VERSION_1_3(instance) + loadVK_VERSION_1_2(instance) + vkGetDescriptorSetLayoutSizeEXT = cast[proc(device: VkDevice, layout: VkDescriptorSetLayout, pLayoutSizeInBytes: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorSetLayoutSizeEXT")) + vkGetDescriptorSetLayoutBindingOffsetEXT = cast[proc(device: VkDevice, layout: VkDescriptorSetLayout, binding: uint32, pOffset: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorSetLayoutBindingOffsetEXT")) + vkGetDescriptorEXT = cast[proc(device: VkDevice, pDescriptorInfo: ptr VkDescriptorGetInfoEXT, dataSize: csize_t, pDescriptor: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorEXT")) + vkCmdBindDescriptorBuffersEXT = cast[proc(commandBuffer: VkCommandBuffer, bufferCount: uint32, pBindingInfos: ptr VkDescriptorBufferBindingInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindDescriptorBuffersEXT")) + vkCmdSetDescriptorBufferOffsetsEXT = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, firstSet: uint32, setCount: uint32, pBufferIndices: ptr uint32, pOffsets: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDescriptorBufferOffsetsEXT")) + vkCmdBindDescriptorBufferEmbeddedSamplersEXT = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, set: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindDescriptorBufferEmbeddedSamplersEXT")) + vkGetBufferOpaqueCaptureDescriptorDataEXT = cast[proc(device: VkDevice, pInfo: ptr VkBufferCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferOpaqueCaptureDescriptorDataEXT")) + vkGetImageOpaqueCaptureDescriptorDataEXT = cast[proc(device: VkDevice, pInfo: ptr VkImageCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageOpaqueCaptureDescriptorDataEXT")) + vkGetImageViewOpaqueCaptureDescriptorDataEXT = cast[proc(device: VkDevice, pInfo: ptr VkImageViewCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageViewOpaqueCaptureDescriptorDataEXT")) + vkGetSamplerOpaqueCaptureDescriptorDataEXT = cast[proc(device: VkDevice, pInfo: ptr VkSamplerCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSamplerOpaqueCaptureDescriptorDataEXT")) + vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT = cast[proc(device: VkDevice, pInfo: ptr VkAccelerationStructureCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT")) + +# extension VK_KHR_performance_query +var + vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, pCounterCount: ptr uint32, pCounters: ptr VkPerformanceCounterKHR, pCounterDescriptions: ptr VkPerformanceCounterDescriptionKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR*: proc(physicalDevice: VkPhysicalDevice, pPerformanceQueryCreateInfo: ptr VkQueryPoolPerformanceCreateInfoKHR, pNumPasses: ptr uint32): void {.stdcall.} + vkAcquireProfilingLockKHR*: proc(device: VkDevice, pInfo: ptr VkAcquireProfilingLockInfoKHR): VkResult {.stdcall.} + vkReleaseProfilingLockKHR*: proc(device: VkDevice): void {.stdcall.} +proc loadVK_KHR_performance_query*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, pCounterCount: ptr uint32, pCounters: ptr VkPerformanceCounterKHR, pCounterDescriptions: ptr VkPerformanceCounterDescriptionKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR")) + vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pPerformanceQueryCreateInfo: ptr VkQueryPoolPerformanceCreateInfoKHR, pNumPasses: ptr uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR")) + vkAcquireProfilingLockKHR = cast[proc(device: VkDevice, pInfo: ptr VkAcquireProfilingLockInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireProfilingLockKHR")) + vkReleaseProfilingLockKHR = cast[proc(device: VkDevice): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkReleaseProfilingLockKHR")) + +proc loadVK_GOOGLE_user_type*(instance: VkInstance) = + discard + +# extension VK_EXT_debug_report +var + vkCreateDebugReportCallbackEXT*: proc(instance: VkInstance, pCreateInfo: ptr VkDebugReportCallbackCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pCallback: ptr VkDebugReportCallbackEXT): VkResult {.stdcall.} + vkDestroyDebugReportCallbackEXT*: proc(instance: VkInstance, callback: VkDebugReportCallbackEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkDebugReportMessageEXT*: proc(instance: VkInstance, flags: VkDebugReportFlagsEXT, objectType: VkDebugReportObjectTypeEXT, theobject: uint64, location: csize_t, messageCode: int32, pLayerPrefix: cstring, pMessage: cstring): void {.stdcall.} +proc loadVK_EXT_debug_report*(instance: VkInstance) = + vkCreateDebugReportCallbackEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDebugReportCallbackCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pCallback: ptr VkDebugReportCallbackEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT")) + vkDestroyDebugReportCallbackEXT = cast[proc(instance: VkInstance, callback: VkDebugReportCallbackEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT")) + vkDebugReportMessageEXT = cast[proc(instance: VkInstance, flags: VkDebugReportFlagsEXT, objectType: VkDebugReportObjectTypeEXT, theobject: uint64, location: csize_t, messageCode: int32, pLayerPrefix: cstring, pMessage: cstring): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDebugReportMessageEXT")) + +proc loadVK_EXT_multisampled_render_to_single_sampled*(instance: VkInstance) = + loadVK_VERSION_1_2(instance) + loadVK_VERSION_1_2(instance) + +proc loadVK_AMD_negative_viewport_height*(instance: VkInstance) = + discard + +proc loadVK_EXT_provoking_vertex*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_NV_device_diagnostics_config*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_NV_shader_subgroup_partitioned*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_image_sliced_view_of_3d*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_1(instance) + +proc loadVK_AMD_shader_image_load_store_lod*(instance: VkInstance) = + discard + +proc loadVK_INTEL_shader_integer_functions2*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_image_2d_view_of_3d*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_1(instance) + +# extension VK_NV_shading_rate_image +var + vkCmdBindShadingRateImageNV*: proc(commandBuffer: VkCommandBuffer, imageView: VkImageView, imageLayout: VkImageLayout): void {.stdcall.} + vkCmdSetViewportShadingRatePaletteNV*: proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pShadingRatePalettes: ptr VkShadingRatePaletteNV): void {.stdcall.} + vkCmdSetCoarseSampleOrderNV*: proc(commandBuffer: VkCommandBuffer, sampleOrderType: VkCoarseSampleOrderTypeNV, customSampleOrderCount: uint32, pCustomSampleOrders: ptr VkCoarseSampleOrderCustomNV): void {.stdcall.} +proc loadVK_NV_shading_rate_image*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdBindShadingRateImageNV = cast[proc(commandBuffer: VkCommandBuffer, imageView: VkImageView, imageLayout: VkImageLayout): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindShadingRateImageNV")) + vkCmdSetViewportShadingRatePaletteNV = cast[proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pShadingRatePalettes: ptr VkShadingRatePaletteNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewportShadingRatePaletteNV")) + vkCmdSetCoarseSampleOrderNV = cast[proc(commandBuffer: VkCommandBuffer, sampleOrderType: VkCoarseSampleOrderTypeNV, customSampleOrderCount: uint32, pCustomSampleOrders: ptr VkCoarseSampleOrderCustomNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoarseSampleOrderNV")) + +proc loadVK_EXT_fragment_density_map*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_NV_device_diagnostic_checkpoints +var + vkCmdSetCheckpointNV*: proc(commandBuffer: VkCommandBuffer, pCheckpointMarker: pointer): void {.stdcall.} + vkGetQueueCheckpointDataNV*: proc(queue: VkQueue, pCheckpointDataCount: ptr uint32, pCheckpointData: ptr VkCheckpointDataNV): void {.stdcall.} +proc loadVK_NV_device_diagnostic_checkpoints*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdSetCheckpointNV = cast[proc(commandBuffer: VkCommandBuffer, pCheckpointMarker: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCheckpointNV")) + vkGetQueueCheckpointDataNV = cast[proc(queue: VkQueue, pCheckpointDataCount: ptr uint32, pCheckpointData: ptr VkCheckpointDataNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetQueueCheckpointDataNV")) + +proc loadVK_EXT_pci_bus_info*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_queue_family_foreign*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_EXT_debug_utils +var + vkSetDebugUtilsObjectNameEXT*: proc(device: VkDevice, pNameInfo: ptr VkDebugUtilsObjectNameInfoEXT): VkResult {.stdcall.} + vkSetDebugUtilsObjectTagEXT*: proc(device: VkDevice, pTagInfo: ptr VkDebugUtilsObjectTagInfoEXT): VkResult {.stdcall.} + vkQueueBeginDebugUtilsLabelEXT*: proc(queue: VkQueue, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.} + vkQueueEndDebugUtilsLabelEXT*: proc(queue: VkQueue): void {.stdcall.} + vkQueueInsertDebugUtilsLabelEXT*: proc(queue: VkQueue, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.} + vkCmdBeginDebugUtilsLabelEXT*: proc(commandBuffer: VkCommandBuffer, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.} + vkCmdEndDebugUtilsLabelEXT*: proc(commandBuffer: VkCommandBuffer): void {.stdcall.} + vkCmdInsertDebugUtilsLabelEXT*: proc(commandBuffer: VkCommandBuffer, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.} + vkCreateDebugUtilsMessengerEXT*: proc(instance: VkInstance, pCreateInfo: ptr VkDebugUtilsMessengerCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pMessenger: ptr VkDebugUtilsMessengerEXT): VkResult {.stdcall.} + vkDestroyDebugUtilsMessengerEXT*: proc(instance: VkInstance, messenger: VkDebugUtilsMessengerEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkSubmitDebugUtilsMessageEXT*: proc(instance: VkInstance, messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, messageTypes: VkDebugUtilsMessageTypeFlagsEXT, pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT): void {.stdcall.} +proc loadVK_EXT_debug_utils*(instance: VkInstance) = + vkSetDebugUtilsObjectNameEXT = cast[proc(device: VkDevice, pNameInfo: ptr VkDebugUtilsObjectNameInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT")) + vkSetDebugUtilsObjectTagEXT = cast[proc(device: VkDevice, pTagInfo: ptr VkDebugUtilsObjectTagInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectTagEXT")) + vkQueueBeginDebugUtilsLabelEXT = cast[proc(queue: VkQueue, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueBeginDebugUtilsLabelEXT")) + vkQueueEndDebugUtilsLabelEXT = cast[proc(queue: VkQueue): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueEndDebugUtilsLabelEXT")) + vkQueueInsertDebugUtilsLabelEXT = cast[proc(queue: VkQueue, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueInsertDebugUtilsLabelEXT")) + vkCmdBeginDebugUtilsLabelEXT = cast[proc(commandBuffer: VkCommandBuffer, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT")) + vkCmdEndDebugUtilsLabelEXT = cast[proc(commandBuffer: VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT")) + vkCmdInsertDebugUtilsLabelEXT = cast[proc(commandBuffer: VkCommandBuffer, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdInsertDebugUtilsLabelEXT")) + vkCreateDebugUtilsMessengerEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDebugUtilsMessengerCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pMessenger: ptr VkDebugUtilsMessengerEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT")) + vkDestroyDebugUtilsMessengerEXT = cast[proc(instance: VkInstance, messenger: VkDebugUtilsMessengerEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT")) + vkSubmitDebugUtilsMessageEXT = cast[proc(instance: VkInstance, messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, messageTypes: VkDebugUtilsMessageTypeFlagsEXT, pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSubmitDebugUtilsMessageEXT")) + +proc loadVK_KHR_portability_enumeration*(instance: VkInstance) = + discard + +proc loadVK_EXT_memory_priority*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_AMD_shader_core_properties*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_KHR_external_fence_fd +var + vkImportFenceFdKHR*: proc(device: VkDevice, pImportFenceFdInfo: ptr VkImportFenceFdInfoKHR): VkResult {.stdcall.} + vkGetFenceFdKHR*: proc(device: VkDevice, pGetFdInfo: ptr VkFenceGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.} +proc loadVK_KHR_external_fence_fd*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkImportFenceFdKHR = cast[proc(device: VkDevice, pImportFenceFdInfo: ptr VkImportFenceFdInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkImportFenceFdKHR")) + vkGetFenceFdKHR = cast[proc(device: VkDevice, pGetFdInfo: ptr VkFenceGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetFenceFdKHR")) + +# extension VK_NV_device_generated_commands +var + vkGetGeneratedCommandsMemoryRequirementsNV*: proc(device: VkDevice, pInfo: ptr VkGeneratedCommandsMemoryRequirementsInfoNV, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.} + vkCmdPreprocessGeneratedCommandsNV*: proc(commandBuffer: VkCommandBuffer, pGeneratedCommandsInfo: ptr VkGeneratedCommandsInfoNV): void {.stdcall.} + vkCmdExecuteGeneratedCommandsNV*: proc(commandBuffer: VkCommandBuffer, isPreprocessed: VkBool32, pGeneratedCommandsInfo: ptr VkGeneratedCommandsInfoNV): void {.stdcall.} + vkCmdBindPipelineShaderGroupNV*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, pipeline: VkPipeline, groupIndex: uint32): void {.stdcall.} + vkCreateIndirectCommandsLayoutNV*: proc(device: VkDevice, pCreateInfo: ptr VkIndirectCommandsLayoutCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pIndirectCommandsLayout: ptr VkIndirectCommandsLayoutNV): VkResult {.stdcall.} + vkDestroyIndirectCommandsLayoutNV*: proc(device: VkDevice, indirectCommandsLayout: VkIndirectCommandsLayoutNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} +proc loadVK_NV_device_generated_commands*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_2(instance) + vkGetGeneratedCommandsMemoryRequirementsNV = cast[proc(device: VkDevice, pInfo: ptr VkGeneratedCommandsMemoryRequirementsInfoNV, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetGeneratedCommandsMemoryRequirementsNV")) + vkCmdPreprocessGeneratedCommandsNV = cast[proc(commandBuffer: VkCommandBuffer, pGeneratedCommandsInfo: ptr VkGeneratedCommandsInfoNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPreprocessGeneratedCommandsNV")) + vkCmdExecuteGeneratedCommandsNV = cast[proc(commandBuffer: VkCommandBuffer, isPreprocessed: VkBool32, pGeneratedCommandsInfo: ptr VkGeneratedCommandsInfoNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdExecuteGeneratedCommandsNV")) + vkCmdBindPipelineShaderGroupNV = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, pipeline: VkPipeline, groupIndex: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindPipelineShaderGroupNV")) + vkCreateIndirectCommandsLayoutNV = cast[proc(device: VkDevice, pCreateInfo: ptr VkIndirectCommandsLayoutCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pIndirectCommandsLayout: ptr VkIndirectCommandsLayoutNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateIndirectCommandsLayoutNV")) + vkDestroyIndirectCommandsLayoutNV = cast[proc(device: VkDevice, indirectCommandsLayout: VkIndirectCommandsLayoutNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyIndirectCommandsLayoutNV")) + +proc loadVK_NV_viewport_array2*(instance: VkInstance) = + discard + +proc loadVK_NVX_multiview_per_view_attributes*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_KHR_external_memory_fd +var + vkGetMemoryFdKHR*: proc(device: VkDevice, pGetFdInfo: ptr VkMemoryGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.} + vkGetMemoryFdPropertiesKHR*: proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, fd: cint, pMemoryFdProperties: ptr VkMemoryFdPropertiesKHR): VkResult {.stdcall.} +proc loadVK_KHR_external_memory_fd*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetMemoryFdKHR = cast[proc(device: VkDevice, pGetFdInfo: ptr VkMemoryGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryFdKHR")) + vkGetMemoryFdPropertiesKHR = cast[proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, fd: cint, pMemoryFdProperties: ptr VkMemoryFdPropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryFdPropertiesKHR")) + +proc loadVK_EXT_rgba10x6_formats*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_NV_dedicated_allocation_image_aliasing*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_1(instance) + +# extension VK_NV_cooperative_matrix +var + vkGetPhysicalDeviceCooperativeMatrixPropertiesNV*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkCooperativeMatrixPropertiesNV): VkResult {.stdcall.} +proc loadVK_NV_cooperative_matrix*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetPhysicalDeviceCooperativeMatrixPropertiesNV = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkCooperativeMatrixPropertiesNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV")) + +proc loadVK_EXT_depth_clamp_zero_one*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_NV_linear_color_attachment*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_shader_subgroup_ballot*(instance: VkInstance) = + discard + +# extension VK_EXT_image_drm_format_modifier +var + vkGetImageDrmFormatModifierPropertiesEXT*: proc(device: VkDevice, image: VkImage, pProperties: ptr VkImageDrmFormatModifierPropertiesEXT): VkResult {.stdcall.} +proc loadVK_EXT_image_drm_format_modifier*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_2(instance) + loadVK_VERSION_1_1(instance) + vkGetImageDrmFormatModifierPropertiesEXT = cast[proc(device: VkDevice, image: VkImage, pProperties: ptr VkImageDrmFormatModifierPropertiesEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageDrmFormatModifierPropertiesEXT")) + +# extension VK_EXT_mesh_shader +var + vkCmdDrawMeshTasksEXT*: proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.} + vkCmdDrawMeshTasksIndirectEXT*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.} + vkCmdDrawMeshTasksIndirectCountEXT*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.} +proc loadVK_EXT_mesh_shader*(instance: VkInstance) = + loadVK_VERSION_1_2(instance) + vkCmdDrawMeshTasksEXT = cast[proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksEXT")) + vkCmdDrawMeshTasksIndirectEXT = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectEXT")) + vkCmdDrawMeshTasksIndirectCountEXT = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectCountEXT")) + +# extension VK_EXT_transform_feedback +var + vkCmdBindTransformFeedbackBuffersEXT*: proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize, pSizes: ptr VkDeviceSize): void {.stdcall.} + vkCmdBeginTransformFeedbackEXT*: proc(commandBuffer: VkCommandBuffer, firstCounterBuffer: uint32, counterBufferCount: uint32, pCounterBuffers: ptr VkBuffer, pCounterBufferOffsets: ptr VkDeviceSize): void {.stdcall.} + vkCmdEndTransformFeedbackEXT*: proc(commandBuffer: VkCommandBuffer, firstCounterBuffer: uint32, counterBufferCount: uint32, pCounterBuffers: ptr VkBuffer, pCounterBufferOffsets: ptr VkDeviceSize): void {.stdcall.} + vkCmdBeginQueryIndexedEXT*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, flags: VkQueryControlFlags, index: uint32): void {.stdcall.} + vkCmdEndQueryIndexedEXT*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, index: uint32): void {.stdcall.} + vkCmdDrawIndirectByteCountEXT*: proc(commandBuffer: VkCommandBuffer, instanceCount: uint32, firstInstance: uint32, counterBuffer: VkBuffer, counterBufferOffset: VkDeviceSize, counterOffset: uint32, vertexStride: uint32): void {.stdcall.} +proc loadVK_EXT_transform_feedback*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdBindTransformFeedbackBuffersEXT = cast[proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize, pSizes: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindTransformFeedbackBuffersEXT")) + vkCmdBeginTransformFeedbackEXT = cast[proc(commandBuffer: VkCommandBuffer, firstCounterBuffer: uint32, counterBufferCount: uint32, pCounterBuffers: ptr VkBuffer, pCounterBufferOffsets: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginTransformFeedbackEXT")) + vkCmdEndTransformFeedbackEXT = cast[proc(commandBuffer: VkCommandBuffer, firstCounterBuffer: uint32, counterBufferCount: uint32, pCounterBuffers: ptr VkBuffer, pCounterBufferOffsets: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndTransformFeedbackEXT")) + vkCmdBeginQueryIndexedEXT = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, flags: VkQueryControlFlags, index: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginQueryIndexedEXT")) + vkCmdEndQueryIndexedEXT = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, index: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndQueryIndexedEXT")) + vkCmdDrawIndirectByteCountEXT = cast[proc(commandBuffer: VkCommandBuffer, instanceCount: uint32, firstInstance: uint32, counterBuffer: VkBuffer, counterBufferOffset: VkDeviceSize, counterOffset: uint32, vertexStride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndirectByteCountEXT")) + +proc loadVK_AMD_shader_early_and_late_fragment_tests*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_AMD_shader_core_properties2*(instance: VkInstance) = + loadVK_AMD_shader_core_properties(instance) + +proc loadVK_GOOGLE_hlsl_functionality1*(instance: VkInstance) = + discard + +proc loadVK_EXT_robustness2*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_image_view_min_lod*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_AMD_shader_trinary_minmax*(instance: VkInstance) = + discard + +proc loadVK_EXT_custom_border_color*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_AMD_rasterization_order*(instance: VkInstance) = + discard + +# extension VK_EXT_vertex_input_dynamic_state +var + vkCmdSetVertexInputEXT*: proc(commandBuffer: VkCommandBuffer, vertexBindingDescriptionCount: uint32, pVertexBindingDescriptions: ptr VkVertexInputBindingDescription2EXT, vertexAttributeDescriptionCount: uint32, pVertexAttributeDescriptions: ptr VkVertexInputAttributeDescription2EXT): void {.stdcall.} +proc loadVK_EXT_vertex_input_dynamic_state*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdSetVertexInputEXT = cast[proc(commandBuffer: VkCommandBuffer, vertexBindingDescriptionCount: uint32, pVertexBindingDescriptions: ptr VkVertexInputBindingDescription2EXT, vertexAttributeDescriptionCount: uint32, pVertexAttributeDescriptions: ptr VkVertexInputAttributeDescription2EXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetVertexInputEXT")) + +# extension VK_KHR_fragment_shading_rate +var + vkGetPhysicalDeviceFragmentShadingRatesKHR*: proc(physicalDevice: VkPhysicalDevice, pFragmentShadingRateCount: ptr uint32, pFragmentShadingRates: ptr VkPhysicalDeviceFragmentShadingRateKHR): VkResult {.stdcall.} + vkCmdSetFragmentShadingRateKHR*: proc(commandBuffer: VkCommandBuffer, pFragmentSize: ptr VkExtent2D, combinerOps: array[2, VkFragmentShadingRateCombinerOpKHR]): void {.stdcall.} +proc loadVK_KHR_fragment_shading_rate*(instance: VkInstance) = + loadVK_VERSION_1_2(instance) + loadVK_VERSION_1_1(instance) + vkGetPhysicalDeviceFragmentShadingRatesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pFragmentShadingRateCount: ptr uint32, pFragmentShadingRates: ptr VkPhysicalDeviceFragmentShadingRateKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFragmentShadingRatesKHR")) + vkCmdSetFragmentShadingRateKHR = cast[proc(commandBuffer: VkCommandBuffer, pFragmentSize: ptr VkExtent2D, combinerOps: array[2, VkFragmentShadingRateCombinerOpKHR]): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetFragmentShadingRateKHR")) + +proc loadVK_EXT_depth_clip_enable*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_subpass_merge_feedback*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_KHR_external_semaphore_fd +var + vkImportSemaphoreFdKHR*: proc(device: VkDevice, pImportSemaphoreFdInfo: ptr VkImportSemaphoreFdInfoKHR): VkResult {.stdcall.} + vkGetSemaphoreFdKHR*: proc(device: VkDevice, pGetFdInfo: ptr VkSemaphoreGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.} +proc loadVK_KHR_external_semaphore_fd*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkImportSemaphoreFdKHR = cast[proc(device: VkDevice, pImportSemaphoreFdInfo: ptr VkImportSemaphoreFdInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkImportSemaphoreFdKHR")) + vkGetSemaphoreFdKHR = cast[proc(device: VkDevice, pGetFdInfo: ptr VkSemaphoreGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSemaphoreFdKHR")) + +proc loadVK_KHR_fragment_shader_barycentric*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_memory_budget*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_AMD_device_coherent_memory*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_device_memory_report*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_AMD_memory_overallocation_behavior*(instance: VkInstance) = + discard + +# extension VK_NV_mesh_shader +var + vkCmdDrawMeshTasksNV*: proc(commandBuffer: VkCommandBuffer, taskCount: uint32, firstTask: uint32): void {.stdcall.} + vkCmdDrawMeshTasksIndirectNV*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.} + vkCmdDrawMeshTasksIndirectCountNV*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.} +proc loadVK_NV_mesh_shader*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdDrawMeshTasksNV = cast[proc(commandBuffer: VkCommandBuffer, taskCount: uint32, firstTask: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksNV")) + vkCmdDrawMeshTasksIndirectNV = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectNV")) + vkCmdDrawMeshTasksIndirectCountNV = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectCountNV")) + +# extension VK_EXT_image_compression_control +var + vkGetImageSubresourceLayout2EXT*: proc(device: VkDevice, image: VkImage, pSubresource: ptr VkImageSubresource2EXT, pLayout: ptr VkSubresourceLayout2EXT): void {.stdcall.} +proc loadVK_EXT_image_compression_control*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetImageSubresourceLayout2EXT = cast[proc(device: VkDevice, image: VkImage, pSubresource: ptr VkImageSubresource2EXT, pLayout: ptr VkSubresourceLayout2EXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageSubresourceLayout2EXT")) + +# extension VK_EXT_buffer_device_address +var + vkGetBufferDeviceAddressEXT*: proc(device: VkDevice, pInfo: ptr VkBufferDeviceAddressInfo): VkDeviceAddress {.stdcall.} +proc loadVK_EXT_buffer_device_address*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetBufferDeviceAddressEXT = vkGetBufferDeviceAddress + +proc loadVK_QCOM_render_pass_shader_resolve*(instance: VkInstance) = + discard + +proc loadVK_EXT_depth_range_unrestricted*(instance: VkInstance) = + discard + +# extension VK_HUAWEI_subpass_shading +var + vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI*: proc(device: VkDevice, renderpass: VkRenderPass, pMaxWorkgroupSize: ptr VkExtent2D): VkResult {.stdcall.} + vkCmdSubpassShadingHUAWEI*: proc(commandBuffer: VkCommandBuffer): void {.stdcall.} +proc loadVK_HUAWEI_subpass_shading*(instance: VkInstance) = + loadVK_VERSION_1_2(instance) + loadVK_VERSION_1_3(instance) + vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = cast[proc(device: VkDevice, renderpass: VkRenderPass, pMaxWorkgroupSize: ptr VkExtent2D): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI")) + vkCmdSubpassShadingHUAWEI = cast[proc(commandBuffer: VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSubpassShadingHUAWEI")) + +# extension VK_VALVE_descriptor_set_host_mapping +var + vkGetDescriptorSetLayoutHostMappingInfoVALVE*: proc(device: VkDevice, pBindingReference: ptr VkDescriptorSetBindingReferenceVALVE, pHostMapping: ptr VkDescriptorSetLayoutHostMappingInfoVALVE): void {.stdcall.} + vkGetDescriptorSetHostMappingVALVE*: proc(device: VkDevice, descriptorSet: VkDescriptorSet, ppData: ptr pointer): void {.stdcall.} +proc loadVK_VALVE_descriptor_set_host_mapping*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetDescriptorSetLayoutHostMappingInfoVALVE = cast[proc(device: VkDevice, pBindingReference: ptr VkDescriptorSetBindingReferenceVALVE, pHostMapping: ptr VkDescriptorSetLayoutHostMappingInfoVALVE): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorSetLayoutHostMappingInfoVALVE")) + vkGetDescriptorSetHostMappingVALVE = cast[proc(device: VkDevice, descriptorSet: VkDescriptorSet, ppData: ptr pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorSetHostMappingVALVE")) + +# extension VK_NV_external_memory_capabilities +var + vkGetPhysicalDeviceExternalImageFormatPropertiesNV*: proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, tiling: VkImageTiling, usage: VkImageUsageFlags, flags: VkImageCreateFlags, externalHandleType: VkExternalMemoryHandleTypeFlagsNV, pExternalImageFormatProperties: ptr VkExternalImageFormatPropertiesNV): VkResult {.stdcall.} +proc loadVK_NV_external_memory_capabilities*(instance: VkInstance) = + vkGetPhysicalDeviceExternalImageFormatPropertiesNV = cast[proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, tiling: VkImageTiling, usage: VkImageUsageFlags, flags: VkImageCreateFlags, externalHandleType: VkExternalMemoryHandleTypeFlagsNV, pExternalImageFormatProperties: ptr VkExternalImageFormatPropertiesNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV")) + +# extension VK_NV_optical_flow +var + vkGetPhysicalDeviceOpticalFlowImageFormatsNV*: proc(physicalDevice: VkPhysicalDevice, pOpticalFlowImageFormatInfo: ptr VkOpticalFlowImageFormatInfoNV, pFormatCount: ptr uint32, pImageFormatProperties: ptr VkOpticalFlowImageFormatPropertiesNV): VkResult {.stdcall.} + vkCreateOpticalFlowSessionNV*: proc(device: VkDevice, pCreateInfo: ptr VkOpticalFlowSessionCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pSession: ptr VkOpticalFlowSessionNV): VkResult {.stdcall.} + vkDestroyOpticalFlowSessionNV*: proc(device: VkDevice, session: VkOpticalFlowSessionNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkBindOpticalFlowSessionImageNV*: proc(device: VkDevice, session: VkOpticalFlowSessionNV, bindingPoint: VkOpticalFlowSessionBindingPointNV, view: VkImageView, layout: VkImageLayout): VkResult {.stdcall.} + vkCmdOpticalFlowExecuteNV*: proc(commandBuffer: VkCommandBuffer, session: VkOpticalFlowSessionNV, pExecuteInfo: ptr VkOpticalFlowExecuteInfoNV): void {.stdcall.} +proc loadVK_NV_optical_flow*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_3(instance) + loadVK_VERSION_1_3(instance) + vkGetPhysicalDeviceOpticalFlowImageFormatsNV = cast[proc(physicalDevice: VkPhysicalDevice, pOpticalFlowImageFormatInfo: ptr VkOpticalFlowImageFormatInfoNV, pFormatCount: ptr uint32, pImageFormatProperties: ptr VkOpticalFlowImageFormatPropertiesNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceOpticalFlowImageFormatsNV")) + vkCreateOpticalFlowSessionNV = cast[proc(device: VkDevice, pCreateInfo: ptr VkOpticalFlowSessionCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pSession: ptr VkOpticalFlowSessionNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateOpticalFlowSessionNV")) + vkDestroyOpticalFlowSessionNV = cast[proc(device: VkDevice, session: VkOpticalFlowSessionNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyOpticalFlowSessionNV")) + vkBindOpticalFlowSessionImageNV = cast[proc(device: VkDevice, session: VkOpticalFlowSessionNV, bindingPoint: VkOpticalFlowSessionBindingPointNV, view: VkImageView, layout: VkImageLayout): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindOpticalFlowSessionImageNV")) + vkCmdOpticalFlowExecuteNV = cast[proc(commandBuffer: VkCommandBuffer, session: VkOpticalFlowSessionNV, pExecuteInfo: ptr VkOpticalFlowExecuteInfoNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdOpticalFlowExecuteNV")) + +proc loadVK_EXT_vertex_attribute_divisor*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_EXT_line_rasterization +var + vkCmdSetLineStippleEXT*: proc(commandBuffer: VkCommandBuffer, lineStippleFactor: uint32, lineStipplePattern: uint16): void {.stdcall.} +proc loadVK_EXT_line_rasterization*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdSetLineStippleEXT = cast[proc(commandBuffer: VkCommandBuffer, lineStippleFactor: uint32, lineStipplePattern: uint16): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetLineStippleEXT")) + +proc loadVK_AMD_texture_gather_bias_lod*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_KHR_shader_subgroup_uniform_control_flow*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_external_memory_dma_buf*(instance: VkInstance) = + loadVK_KHR_external_memory_fd(instance) + +proc loadVK_IMG_filter_cubic*(instance: VkInstance) = + discard + +proc loadVK_AMD_shader_ballot*(instance: VkInstance) = + discard + +# extension VK_AMD_buffer_marker +var + vkCmdWriteBufferMarkerAMD*: proc(commandBuffer: VkCommandBuffer, pipelineStage: VkPipelineStageFlagBits, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, marker: uint32): void {.stdcall.} +proc loadVK_AMD_buffer_marker*(instance: VkInstance) = + vkCmdWriteBufferMarkerAMD = cast[proc(commandBuffer: VkCommandBuffer, pipelineStage: VkPipelineStageFlagBits, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, marker: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteBufferMarkerAMD")) + +proc loadVK_NV_corner_sampled_image*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_KHR_pipeline_library*(instance: VkInstance) = + discard + +proc loadVK_EXT_blend_operation_advanced*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_NV_scissor_exclusive +var + vkCmdSetExclusiveScissorEnableNV*: proc(commandBuffer: VkCommandBuffer, firstExclusiveScissor: uint32, exclusiveScissorCount: uint32, pExclusiveScissorEnables: ptr VkBool32): void {.stdcall.} + vkCmdSetExclusiveScissorNV*: proc(commandBuffer: VkCommandBuffer, firstExclusiveScissor: uint32, exclusiveScissorCount: uint32, pExclusiveScissors: ptr VkRect2D): void {.stdcall.} +proc loadVK_NV_scissor_exclusive*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdSetExclusiveScissorEnableNV = cast[proc(commandBuffer: VkCommandBuffer, firstExclusiveScissor: uint32, exclusiveScissorCount: uint32, pExclusiveScissorEnables: ptr VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetExclusiveScissorEnableNV")) + vkCmdSetExclusiveScissorNV = cast[proc(commandBuffer: VkCommandBuffer, firstExclusiveScissor: uint32, exclusiveScissorCount: uint32, pExclusiveScissors: ptr VkRect2D): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetExclusiveScissorNV")) + +proc loadVK_NV_framebuffer_mixed_samples*(instance: VkInstance) = + discard + +proc loadVK_NV_sample_mask_override_coverage*(instance: VkInstance) = + discard + +proc loadVK_EXT_filter_cubic*(instance: VkInstance) = + discard + +# extension VK_KHR_pipeline_executable_properties +var + vkGetPipelineExecutablePropertiesKHR*: proc(device: VkDevice, pPipelineInfo: ptr VkPipelineInfoKHR, pExecutableCount: ptr uint32, pProperties: ptr VkPipelineExecutablePropertiesKHR): VkResult {.stdcall.} + vkGetPipelineExecutableStatisticsKHR*: proc(device: VkDevice, pExecutableInfo: ptr VkPipelineExecutableInfoKHR, pStatisticCount: ptr uint32, pStatistics: ptr VkPipelineExecutableStatisticKHR): VkResult {.stdcall.} + vkGetPipelineExecutableInternalRepresentationsKHR*: proc(device: VkDevice, pExecutableInfo: ptr VkPipelineExecutableInfoKHR, pInternalRepresentationCount: ptr uint32, pInternalRepresentations: ptr VkPipelineExecutableInternalRepresentationKHR): VkResult {.stdcall.} +proc loadVK_KHR_pipeline_executable_properties*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetPipelineExecutablePropertiesKHR = cast[proc(device: VkDevice, pPipelineInfo: ptr VkPipelineInfoKHR, pExecutableCount: ptr uint32, pProperties: ptr VkPipelineExecutablePropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPipelineExecutablePropertiesKHR")) + vkGetPipelineExecutableStatisticsKHR = cast[proc(device: VkDevice, pExecutableInfo: ptr VkPipelineExecutableInfoKHR, pStatisticCount: ptr uint32, pStatistics: ptr VkPipelineExecutableStatisticKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPipelineExecutableStatisticsKHR")) + vkGetPipelineExecutableInternalRepresentationsKHR = cast[proc(device: VkDevice, pExecutableInfo: ptr VkPipelineExecutableInfoKHR, pInternalRepresentationCount: ptr uint32, pInternalRepresentations: ptr VkPipelineExecutableInternalRepresentationKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPipelineExecutableInternalRepresentationsKHR")) + +# extension VK_EXT_extended_dynamic_state3 +var + vkCmdSetTessellationDomainOriginEXT*: proc(commandBuffer: VkCommandBuffer, domainOrigin: VkTessellationDomainOrigin): void {.stdcall.} + vkCmdSetDepthClampEnableEXT*: proc(commandBuffer: VkCommandBuffer, depthClampEnable: VkBool32): void {.stdcall.} + vkCmdSetPolygonModeEXT*: proc(commandBuffer: VkCommandBuffer, polygonMode: VkPolygonMode): void {.stdcall.} + vkCmdSetRasterizationSamplesEXT*: proc(commandBuffer: VkCommandBuffer, rasterizationSamples: VkSampleCountFlagBits): void {.stdcall.} + vkCmdSetSampleMaskEXT*: proc(commandBuffer: VkCommandBuffer, samples: VkSampleCountFlagBits, pSampleMask: ptr VkSampleMask): void {.stdcall.} + vkCmdSetAlphaToCoverageEnableEXT*: proc(commandBuffer: VkCommandBuffer, alphaToCoverageEnable: VkBool32): void {.stdcall.} + vkCmdSetAlphaToOneEnableEXT*: proc(commandBuffer: VkCommandBuffer, alphaToOneEnable: VkBool32): void {.stdcall.} + vkCmdSetLogicOpEnableEXT*: proc(commandBuffer: VkCommandBuffer, logicOpEnable: VkBool32): void {.stdcall.} + vkCmdSetColorBlendEnableEXT*: proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendEnables: ptr VkBool32): void {.stdcall.} + vkCmdSetColorBlendEquationEXT*: proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendEquations: ptr VkColorBlendEquationEXT): void {.stdcall.} + vkCmdSetColorWriteMaskEXT*: proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorWriteMasks: ptr VkColorComponentFlags): void {.stdcall.} + vkCmdSetRasterizationStreamEXT*: proc(commandBuffer: VkCommandBuffer, rasterizationStream: uint32): void {.stdcall.} + vkCmdSetConservativeRasterizationModeEXT*: proc(commandBuffer: VkCommandBuffer, conservativeRasterizationMode: VkConservativeRasterizationModeEXT): void {.stdcall.} + vkCmdSetExtraPrimitiveOverestimationSizeEXT*: proc(commandBuffer: VkCommandBuffer, extraPrimitiveOverestimationSize: float32): void {.stdcall.} + vkCmdSetDepthClipEnableEXT*: proc(commandBuffer: VkCommandBuffer, depthClipEnable: VkBool32): void {.stdcall.} + vkCmdSetSampleLocationsEnableEXT*: proc(commandBuffer: VkCommandBuffer, sampleLocationsEnable: VkBool32): void {.stdcall.} + vkCmdSetColorBlendAdvancedEXT*: proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendAdvanced: ptr VkColorBlendAdvancedEXT): void {.stdcall.} + vkCmdSetProvokingVertexModeEXT*: proc(commandBuffer: VkCommandBuffer, provokingVertexMode: VkProvokingVertexModeEXT): void {.stdcall.} + vkCmdSetLineRasterizationModeEXT*: proc(commandBuffer: VkCommandBuffer, lineRasterizationMode: VkLineRasterizationModeEXT): void {.stdcall.} + vkCmdSetLineStippleEnableEXT*: proc(commandBuffer: VkCommandBuffer, stippledLineEnable: VkBool32): void {.stdcall.} + vkCmdSetDepthClipNegativeOneToOneEXT*: proc(commandBuffer: VkCommandBuffer, negativeOneToOne: VkBool32): void {.stdcall.} + vkCmdSetViewportWScalingEnableNV*: proc(commandBuffer: VkCommandBuffer, viewportWScalingEnable: VkBool32): void {.stdcall.} + vkCmdSetViewportSwizzleNV*: proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewportSwizzles: ptr VkViewportSwizzleNV): void {.stdcall.} + vkCmdSetCoverageToColorEnableNV*: proc(commandBuffer: VkCommandBuffer, coverageToColorEnable: VkBool32): void {.stdcall.} + vkCmdSetCoverageToColorLocationNV*: proc(commandBuffer: VkCommandBuffer, coverageToColorLocation: uint32): void {.stdcall.} + vkCmdSetCoverageModulationModeNV*: proc(commandBuffer: VkCommandBuffer, coverageModulationMode: VkCoverageModulationModeNV): void {.stdcall.} + vkCmdSetCoverageModulationTableEnableNV*: proc(commandBuffer: VkCommandBuffer, coverageModulationTableEnable: VkBool32): void {.stdcall.} + vkCmdSetCoverageModulationTableNV*: proc(commandBuffer: VkCommandBuffer, coverageModulationTableCount: uint32, pCoverageModulationTable: ptr float32): void {.stdcall.} + vkCmdSetShadingRateImageEnableNV*: proc(commandBuffer: VkCommandBuffer, shadingRateImageEnable: VkBool32): void {.stdcall.} + vkCmdSetRepresentativeFragmentTestEnableNV*: proc(commandBuffer: VkCommandBuffer, representativeFragmentTestEnable: VkBool32): void {.stdcall.} + vkCmdSetCoverageReductionModeNV*: proc(commandBuffer: VkCommandBuffer, coverageReductionMode: VkCoverageReductionModeNV): void {.stdcall.} +proc loadVK_EXT_extended_dynamic_state3*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdSetTessellationDomainOriginEXT = cast[proc(commandBuffer: VkCommandBuffer, domainOrigin: VkTessellationDomainOrigin): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetTessellationDomainOriginEXT")) + vkCmdSetDepthClampEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, depthClampEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthClampEnableEXT")) + vkCmdSetPolygonModeEXT = cast[proc(commandBuffer: VkCommandBuffer, polygonMode: VkPolygonMode): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPolygonModeEXT")) + vkCmdSetRasterizationSamplesEXT = cast[proc(commandBuffer: VkCommandBuffer, rasterizationSamples: VkSampleCountFlagBits): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetRasterizationSamplesEXT")) + vkCmdSetSampleMaskEXT = cast[proc(commandBuffer: VkCommandBuffer, samples: VkSampleCountFlagBits, pSampleMask: ptr VkSampleMask): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetSampleMaskEXT")) + vkCmdSetAlphaToCoverageEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, alphaToCoverageEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetAlphaToCoverageEnableEXT")) + vkCmdSetAlphaToOneEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, alphaToOneEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetAlphaToOneEnableEXT")) + vkCmdSetLogicOpEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, logicOpEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetLogicOpEnableEXT")) + vkCmdSetColorBlendEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendEnables: ptr VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetColorBlendEnableEXT")) + vkCmdSetColorBlendEquationEXT = cast[proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendEquations: ptr VkColorBlendEquationEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetColorBlendEquationEXT")) + vkCmdSetColorWriteMaskEXT = cast[proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorWriteMasks: ptr VkColorComponentFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetColorWriteMaskEXT")) + vkCmdSetRasterizationStreamEXT = cast[proc(commandBuffer: VkCommandBuffer, rasterizationStream: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetRasterizationStreamEXT")) + vkCmdSetConservativeRasterizationModeEXT = cast[proc(commandBuffer: VkCommandBuffer, conservativeRasterizationMode: VkConservativeRasterizationModeEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetConservativeRasterizationModeEXT")) + vkCmdSetExtraPrimitiveOverestimationSizeEXT = cast[proc(commandBuffer: VkCommandBuffer, extraPrimitiveOverestimationSize: float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetExtraPrimitiveOverestimationSizeEXT")) + vkCmdSetDepthClipEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, depthClipEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthClipEnableEXT")) + vkCmdSetSampleLocationsEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, sampleLocationsEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetSampleLocationsEnableEXT")) + vkCmdSetColorBlendAdvancedEXT = cast[proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendAdvanced: ptr VkColorBlendAdvancedEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetColorBlendAdvancedEXT")) + vkCmdSetProvokingVertexModeEXT = cast[proc(commandBuffer: VkCommandBuffer, provokingVertexMode: VkProvokingVertexModeEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetProvokingVertexModeEXT")) + vkCmdSetLineRasterizationModeEXT = cast[proc(commandBuffer: VkCommandBuffer, lineRasterizationMode: VkLineRasterizationModeEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetLineRasterizationModeEXT")) + vkCmdSetLineStippleEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, stippledLineEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetLineStippleEnableEXT")) + vkCmdSetDepthClipNegativeOneToOneEXT = cast[proc(commandBuffer: VkCommandBuffer, negativeOneToOne: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthClipNegativeOneToOneEXT")) + vkCmdSetViewportWScalingEnableNV = cast[proc(commandBuffer: VkCommandBuffer, viewportWScalingEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewportWScalingEnableNV")) + vkCmdSetViewportSwizzleNV = cast[proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewportSwizzles: ptr VkViewportSwizzleNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewportSwizzleNV")) + vkCmdSetCoverageToColorEnableNV = cast[proc(commandBuffer: VkCommandBuffer, coverageToColorEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageToColorEnableNV")) + vkCmdSetCoverageToColorLocationNV = cast[proc(commandBuffer: VkCommandBuffer, coverageToColorLocation: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageToColorLocationNV")) + vkCmdSetCoverageModulationModeNV = cast[proc(commandBuffer: VkCommandBuffer, coverageModulationMode: VkCoverageModulationModeNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageModulationModeNV")) + vkCmdSetCoverageModulationTableEnableNV = cast[proc(commandBuffer: VkCommandBuffer, coverageModulationTableEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageModulationTableEnableNV")) + vkCmdSetCoverageModulationTableNV = cast[proc(commandBuffer: VkCommandBuffer, coverageModulationTableCount: uint32, pCoverageModulationTable: ptr float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageModulationTableNV")) + vkCmdSetShadingRateImageEnableNV = cast[proc(commandBuffer: VkCommandBuffer, shadingRateImageEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetShadingRateImageEnableNV")) + vkCmdSetRepresentativeFragmentTestEnableNV = cast[proc(commandBuffer: VkCommandBuffer, representativeFragmentTestEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetRepresentativeFragmentTestEnableNV")) + vkCmdSetCoverageReductionModeNV = cast[proc(commandBuffer: VkCommandBuffer, coverageReductionMode: VkCoverageReductionModeNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageReductionModeNV")) + +proc loadVK_EXT_device_address_binding_report*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_EXT_debug_utils(instance) + +# extension VK_NV_clip_space_w_scaling +var + vkCmdSetViewportWScalingNV*: proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewportWScalings: ptr VkViewportWScalingNV): void {.stdcall.} +proc loadVK_NV_clip_space_w_scaling*(instance: VkInstance) = + vkCmdSetViewportWScalingNV = cast[proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewportWScalings: ptr VkViewportWScalingNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewportWScalingNV")) + +proc loadVK_NV_fill_rectangle*(instance: VkInstance) = + discard + +proc loadVK_EXT_shader_image_atomic_int64*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_ycbcr_image_arrays*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_EXT_calibrated_timestamps +var + vkGetPhysicalDeviceCalibrateableTimeDomainsEXT*: proc(physicalDevice: VkPhysicalDevice, pTimeDomainCount: ptr uint32, pTimeDomains: ptr VkTimeDomainEXT): VkResult {.stdcall.} + vkGetCalibratedTimestampsEXT*: proc(device: VkDevice, timestampCount: uint32, pTimestampInfos: ptr VkCalibratedTimestampInfoEXT, pTimestamps: ptr uint64, pMaxDeviation: ptr uint64): VkResult {.stdcall.} +proc loadVK_EXT_calibrated_timestamps*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetPhysicalDeviceCalibrateableTimeDomainsEXT = cast[proc(physicalDevice: VkPhysicalDevice, pTimeDomainCount: ptr uint32, pTimeDomains: ptr VkTimeDomainEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT")) + vkGetCalibratedTimestampsEXT = cast[proc(device: VkDevice, timestampCount: uint32, pTimestampInfos: ptr VkCalibratedTimestampInfoEXT, pTimestamps: ptr uint64, pMaxDeviation: ptr uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetCalibratedTimestampsEXT")) + +proc loadVK_EXT_attachment_feedback_loop_layout*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_AMD_mixed_attachment_samples*(instance: VkInstance) = + discard + +# extension VK_EXT_external_memory_host +var + vkGetMemoryHostPointerPropertiesEXT*: proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, pHostPointer: pointer, pMemoryHostPointerProperties: ptr VkMemoryHostPointerPropertiesEXT): VkResult {.stdcall.} +proc loadVK_EXT_external_memory_host*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetMemoryHostPointerPropertiesEXT = cast[proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, pHostPointer: pointer, pMemoryHostPointerProperties: ptr VkMemoryHostPointerPropertiesEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryHostPointerPropertiesEXT")) + +proc loadVK_ARM_shader_core_properties*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_EXT_shader_module_identifier +var + vkGetShaderModuleIdentifierEXT*: proc(device: VkDevice, shaderModule: VkShaderModule, pIdentifier: ptr VkShaderModuleIdentifierEXT): void {.stdcall.} + vkGetShaderModuleCreateInfoIdentifierEXT*: proc(device: VkDevice, pCreateInfo: ptr VkShaderModuleCreateInfo, pIdentifier: ptr VkShaderModuleIdentifierEXT): void {.stdcall.} +proc loadVK_EXT_shader_module_identifier*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_3(instance) + vkGetShaderModuleIdentifierEXT = cast[proc(device: VkDevice, shaderModule: VkShaderModule, pIdentifier: ptr VkShaderModuleIdentifierEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetShaderModuleIdentifierEXT")) + vkGetShaderModuleCreateInfoIdentifierEXT = cast[proc(device: VkDevice, pCreateInfo: ptr VkShaderModuleCreateInfo, pIdentifier: ptr VkShaderModuleIdentifierEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetShaderModuleCreateInfoIdentifierEXT")) + +proc loadVK_EXT_border_color_swizzle*(instance: VkInstance) = + loadVK_EXT_custom_border_color(instance) + +# extension VK_NV_memory_decompression +var + vkCmdDecompressMemoryNV*: proc(commandBuffer: VkCommandBuffer, decompressRegionCount: uint32, pDecompressMemoryRegions: ptr VkDecompressMemoryRegionNV): void {.stdcall.} + vkCmdDecompressMemoryIndirectCountNV*: proc(commandBuffer: VkCommandBuffer, indirectCommandsAddress: VkDeviceAddress, indirectCommandsCountAddress: VkDeviceAddress, stride: uint32): void {.stdcall.} +proc loadVK_NV_memory_decompression*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_2(instance) + vkCmdDecompressMemoryNV = cast[proc(commandBuffer: VkCommandBuffer, decompressRegionCount: uint32, pDecompressMemoryRegions: ptr VkDecompressMemoryRegionNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDecompressMemoryNV")) + vkCmdDecompressMemoryIndirectCountNV = cast[proc(commandBuffer: VkCommandBuffer, indirectCommandsAddress: VkDeviceAddress, indirectCommandsCountAddress: VkDeviceAddress, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDecompressMemoryIndirectCountNV")) + +proc loadVK_EXT_fragment_shader_interlock*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_NV_coverage_reduction_mode +var + vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV*: proc(physicalDevice: VkPhysicalDevice, pCombinationCount: ptr uint32, pCombinations: ptr VkFramebufferMixedSamplesCombinationNV): VkResult {.stdcall.} +proc loadVK_NV_coverage_reduction_mode*(instance: VkInstance) = + loadVK_NV_framebuffer_mixed_samples(instance) + loadVK_VERSION_1_1(instance) + vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = cast[proc(physicalDevice: VkPhysicalDevice, pCombinationCount: ptr uint32, pCombinations: ptr VkFramebufferMixedSamplesCombinationNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV")) + +proc loadVK_NV_glsl_shader*(instance: VkInstance) = + discard + +proc loadVK_KHR_shader_clock*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_QCOM_tile_properties +var + vkGetFramebufferTilePropertiesQCOM*: proc(device: VkDevice, framebuffer: VkFramebuffer, pPropertiesCount: ptr uint32, pProperties: ptr VkTilePropertiesQCOM): VkResult {.stdcall.} + vkGetDynamicRenderingTilePropertiesQCOM*: proc(device: VkDevice, pRenderingInfo: ptr VkRenderingInfo, pProperties: ptr VkTilePropertiesQCOM): VkResult {.stdcall.} +proc loadVK_QCOM_tile_properties*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetFramebufferTilePropertiesQCOM = cast[proc(device: VkDevice, framebuffer: VkFramebuffer, pPropertiesCount: ptr uint32, pProperties: ptr VkTilePropertiesQCOM): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetFramebufferTilePropertiesQCOM")) + vkGetDynamicRenderingTilePropertiesQCOM = cast[proc(device: VkDevice, pRenderingInfo: ptr VkRenderingInfo, pProperties: ptr VkTilePropertiesQCOM): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDynamicRenderingTilePropertiesQCOM")) + +# extension VK_KHR_push_descriptor +var + vkCmdPushDescriptorSetKHR*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, set: uint32, descriptorWriteCount: uint32, pDescriptorWrites: ptr VkWriteDescriptorSet): void {.stdcall.} + vkCmdPushDescriptorSetWithTemplateKHR*: proc(commandBuffer: VkCommandBuffer, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, layout: VkPipelineLayout, set: uint32, pData: pointer): void {.stdcall.} +proc loadVK_KHR_push_descriptor*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdPushDescriptorSetKHR = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, set: uint32, descriptorWriteCount: uint32, pDescriptorWrites: ptr VkWriteDescriptorSet): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPushDescriptorSetKHR")) + vkCmdPushDescriptorSetWithTemplateKHR = cast[proc(commandBuffer: VkCommandBuffer, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, layout: VkPipelineLayout, set: uint32, pData: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPushDescriptorSetWithTemplateKHR")) + vkCmdPushDescriptorSetWithTemplateKHR = cast[proc(commandBuffer: VkCommandBuffer, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, layout: VkPipelineLayout, set: uint32, pData: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPushDescriptorSetWithTemplateKHR")) + +proc loadVK_NV_viewport_swizzle*(instance: VkInstance) = + discard + +proc loadVK_NV_external_memory*(instance: VkInstance) = + loadVK_NV_external_memory_capabilities(instance) + +proc loadVK_EXT_depth_clip_control*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_validation_flags*(instance: VkInstance) = + discard + +proc loadVK_EXT_conservative_rasterization*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_AMD_gcn_shader*(instance: VkInstance) = + discard + +# extension VK_INTEL_performance_query +var + vkInitializePerformanceApiINTEL*: proc(device: VkDevice, pInitializeInfo: ptr VkInitializePerformanceApiInfoINTEL): VkResult {.stdcall.} + vkUninitializePerformanceApiINTEL*: proc(device: VkDevice): void {.stdcall.} + vkCmdSetPerformanceMarkerINTEL*: proc(commandBuffer: VkCommandBuffer, pMarkerInfo: ptr VkPerformanceMarkerInfoINTEL): VkResult {.stdcall.} + vkCmdSetPerformanceStreamMarkerINTEL*: proc(commandBuffer: VkCommandBuffer, pMarkerInfo: ptr VkPerformanceStreamMarkerInfoINTEL): VkResult {.stdcall.} + vkCmdSetPerformanceOverrideINTEL*: proc(commandBuffer: VkCommandBuffer, pOverrideInfo: ptr VkPerformanceOverrideInfoINTEL): VkResult {.stdcall.} + vkAcquirePerformanceConfigurationINTEL*: proc(device: VkDevice, pAcquireInfo: ptr VkPerformanceConfigurationAcquireInfoINTEL, pConfiguration: ptr VkPerformanceConfigurationINTEL): VkResult {.stdcall.} + vkReleasePerformanceConfigurationINTEL*: proc(device: VkDevice, configuration: VkPerformanceConfigurationINTEL): VkResult {.stdcall.} + vkQueueSetPerformanceConfigurationINTEL*: proc(queue: VkQueue, configuration: VkPerformanceConfigurationINTEL): VkResult {.stdcall.} + vkGetPerformanceParameterINTEL*: proc(device: VkDevice, parameter: VkPerformanceParameterTypeINTEL, pValue: ptr VkPerformanceValueINTEL): VkResult {.stdcall.} +proc loadVK_INTEL_performance_query*(instance: VkInstance) = + vkInitializePerformanceApiINTEL = cast[proc(device: VkDevice, pInitializeInfo: ptr VkInitializePerformanceApiInfoINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkInitializePerformanceApiINTEL")) + vkUninitializePerformanceApiINTEL = cast[proc(device: VkDevice): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkUninitializePerformanceApiINTEL")) + vkCmdSetPerformanceMarkerINTEL = cast[proc(commandBuffer: VkCommandBuffer, pMarkerInfo: ptr VkPerformanceMarkerInfoINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPerformanceMarkerINTEL")) + vkCmdSetPerformanceStreamMarkerINTEL = cast[proc(commandBuffer: VkCommandBuffer, pMarkerInfo: ptr VkPerformanceStreamMarkerInfoINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPerformanceStreamMarkerINTEL")) + vkCmdSetPerformanceOverrideINTEL = cast[proc(commandBuffer: VkCommandBuffer, pOverrideInfo: ptr VkPerformanceOverrideInfoINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPerformanceOverrideINTEL")) + vkAcquirePerformanceConfigurationINTEL = cast[proc(device: VkDevice, pAcquireInfo: ptr VkPerformanceConfigurationAcquireInfoINTEL, pConfiguration: ptr VkPerformanceConfigurationINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquirePerformanceConfigurationINTEL")) + vkReleasePerformanceConfigurationINTEL = cast[proc(device: VkDevice, configuration: VkPerformanceConfigurationINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkReleasePerformanceConfigurationINTEL")) + vkQueueSetPerformanceConfigurationINTEL = cast[proc(queue: VkQueue, configuration: VkPerformanceConfigurationINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueSetPerformanceConfigurationINTEL")) + vkGetPerformanceParameterINTEL = cast[proc(device: VkDevice, parameter: VkPerformanceParameterTypeINTEL, pValue: ptr VkPerformanceValueINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPerformanceParameterINTEL")) + +proc loadVK_EXT_primitives_generated_query*(instance: VkInstance) = + loadVK_EXT_transform_feedback(instance) + +proc loadVK_AMD_pipeline_compiler_control*(instance: VkInstance) = + discard + +proc loadVK_EXT_post_depth_coverage*(instance: VkInstance) = + discard + +# extension VK_EXT_conditional_rendering +var + vkCmdBeginConditionalRenderingEXT*: proc(commandBuffer: VkCommandBuffer, pConditionalRenderingBegin: ptr VkConditionalRenderingBeginInfoEXT): void {.stdcall.} + vkCmdEndConditionalRenderingEXT*: proc(commandBuffer: VkCommandBuffer): void {.stdcall.} +proc loadVK_EXT_conditional_rendering*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdBeginConditionalRenderingEXT = cast[proc(commandBuffer: VkCommandBuffer, pConditionalRenderingBegin: ptr VkConditionalRenderingBeginInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginConditionalRenderingEXT")) + vkCmdEndConditionalRenderingEXT = cast[proc(commandBuffer: VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndConditionalRenderingEXT")) + +proc loadVK_QCOM_multiview_per_view_viewports*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_EXT_multi_draw +var + vkCmdDrawMultiEXT*: proc(commandBuffer: VkCommandBuffer, drawCount: uint32, pVertexInfo: ptr VkMultiDrawInfoEXT, instanceCount: uint32, firstInstance: uint32, stride: uint32): void {.stdcall.} + vkCmdDrawMultiIndexedEXT*: proc(commandBuffer: VkCommandBuffer, drawCount: uint32, pIndexInfo: ptr VkMultiDrawIndexedInfoEXT, instanceCount: uint32, firstInstance: uint32, stride: uint32, pVertexOffset: ptr int32): void {.stdcall.} +proc loadVK_EXT_multi_draw*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdDrawMultiEXT = cast[proc(commandBuffer: VkCommandBuffer, drawCount: uint32, pVertexInfo: ptr VkMultiDrawInfoEXT, instanceCount: uint32, firstInstance: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMultiEXT")) + vkCmdDrawMultiIndexedEXT = cast[proc(commandBuffer: VkCommandBuffer, drawCount: uint32, pIndexInfo: ptr VkMultiDrawIndexedInfoEXT, instanceCount: uint32, firstInstance: uint32, stride: uint32, pVertexOffset: ptr int32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMultiIndexedEXT")) + +proc loadVK_NV_fragment_coverage_to_color*(instance: VkInstance) = + discard + +proc loadVK_EXT_load_store_op_none*(instance: VkInstance) = + discard + +proc loadVK_EXT_validation_features*(instance: VkInstance) = + discard + +proc loadVK_KHR_workgroup_memory_explicit_layout*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_index_type_uint8*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_GOOGLE_decorate_string*(instance: VkInstance) = + discard + +proc loadVK_EXT_shader_atomic_float*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_EXT_pipeline_properties +var + vkGetPipelinePropertiesEXT*: proc(device: VkDevice, pPipelineInfo: ptr VkPipelineInfoEXT, pPipelineProperties: ptr VkBaseOutStructure): VkResult {.stdcall.} +proc loadVK_EXT_pipeline_properties*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetPipelinePropertiesEXT = cast[proc(device: VkDevice, pPipelineInfo: ptr VkPipelineInfoEXT, pPipelineProperties: ptr VkBaseOutStructure): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPipelinePropertiesEXT")) + +proc loadVK_EXT_graphics_pipeline_library*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_KHR_pipeline_library(instance) + +# extension VK_KHR_surface +var + vkDestroySurfaceKHR*: proc(instance: VkInstance, surface: VkSurfaceKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetPhysicalDeviceSurfaceSupportKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, surface: VkSurfaceKHR, pSupported: ptr VkBool32): VkResult {.stdcall.} + vkGetPhysicalDeviceSurfaceCapabilitiesKHR*: proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceCapabilities: ptr VkSurfaceCapabilitiesKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceSurfaceFormatsKHR*: proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceFormatCount: ptr uint32, pSurfaceFormats: ptr VkSurfaceFormatKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceSurfacePresentModesKHR*: proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pPresentModeCount: ptr uint32, pPresentModes: ptr VkPresentModeKHR): VkResult {.stdcall.} +proc loadVK_KHR_surface*(instance: VkInstance) = + vkDestroySurfaceKHR = cast[proc(instance: VkInstance, surface: VkSurfaceKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR")) + vkGetPhysicalDeviceSurfaceSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, surface: VkSurfaceKHR, pSupported: ptr VkBool32): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR")) + vkGetPhysicalDeviceSurfaceCapabilitiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceCapabilities: ptr VkSurfaceCapabilitiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR")) + vkGetPhysicalDeviceSurfaceFormatsKHR = cast[proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceFormatCount: ptr uint32, pSurfaceFormats: ptr VkSurfaceFormatKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR")) + vkGetPhysicalDeviceSurfacePresentModesKHR = cast[proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pPresentModeCount: ptr uint32, pPresentModes: ptr VkPresentModeKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR")) + +proc loadVK_AMD_gpu_shader_half_float*(instance: VkInstance) = + discard + +# extension VK_KHR_deferred_host_operations +var + vkCreateDeferredOperationKHR*: proc(device: VkDevice, pAllocator: ptr VkAllocationCallbacks, pDeferredOperation: ptr VkDeferredOperationKHR): VkResult {.stdcall.} + vkDestroyDeferredOperationKHR*: proc(device: VkDevice, operation: VkDeferredOperationKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetDeferredOperationMaxConcurrencyKHR*: proc(device: VkDevice, operation: VkDeferredOperationKHR): uint32 {.stdcall.} + vkGetDeferredOperationResultKHR*: proc(device: VkDevice, operation: VkDeferredOperationKHR): VkResult {.stdcall.} + vkDeferredOperationJoinKHR*: proc(device: VkDevice, operation: VkDeferredOperationKHR): VkResult {.stdcall.} +proc loadVK_KHR_deferred_host_operations*(instance: VkInstance) = + vkCreateDeferredOperationKHR = cast[proc(device: VkDevice, pAllocator: ptr VkAllocationCallbacks, pDeferredOperation: ptr VkDeferredOperationKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDeferredOperationKHR")) + vkDestroyDeferredOperationKHR = cast[proc(device: VkDevice, operation: VkDeferredOperationKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDeferredOperationKHR")) + vkGetDeferredOperationMaxConcurrencyKHR = cast[proc(device: VkDevice, operation: VkDeferredOperationKHR): uint32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeferredOperationMaxConcurrencyKHR")) + vkGetDeferredOperationResultKHR = cast[proc(device: VkDevice, operation: VkDeferredOperationKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeferredOperationResultKHR")) + vkDeferredOperationJoinKHR = cast[proc(device: VkDevice, operation: VkDeferredOperationKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDeferredOperationJoinKHR")) + +proc loadVK_NV_dedicated_allocation*(instance: VkInstance) = + discard + +# extension VK_NVX_image_view_handle +var + vkGetImageViewHandleNVX*: proc(device: VkDevice, pInfo: ptr VkImageViewHandleInfoNVX): uint32 {.stdcall.} + vkGetImageViewAddressNVX*: proc(device: VkDevice, imageView: VkImageView, pProperties: ptr VkImageViewAddressPropertiesNVX): VkResult {.stdcall.} +proc loadVK_NVX_image_view_handle*(instance: VkInstance) = + vkGetImageViewHandleNVX = cast[proc(device: VkDevice, pInfo: ptr VkImageViewHandleInfoNVX): uint32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageViewHandleNVX")) + vkGetImageViewAddressNVX = cast[proc(device: VkDevice, imageView: VkImageView, pProperties: ptr VkImageViewAddressPropertiesNVX): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageViewAddressNVX")) + +proc loadVK_EXT_non_seamless_cube_map*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_QCOM_render_pass_store_ops*(instance: VkInstance) = + discard + +# extension VK_EXT_device_fault +var + vkGetDeviceFaultInfoEXT*: proc(device: VkDevice, pFaultCounts: ptr VkDeviceFaultCountsEXT, pFaultInfo: ptr VkDeviceFaultInfoEXT): VkResult {.stdcall.} +proc loadVK_EXT_device_fault*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetDeviceFaultInfoEXT = cast[proc(device: VkDevice, pFaultCounts: ptr VkDeviceFaultCountsEXT, pFaultInfo: ptr VkDeviceFaultInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceFaultInfoEXT")) + +proc loadVK_EXT_mutable_descriptor_type*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_EXT_color_write_enable +var + vkCmdSetColorWriteEnableEXT*: proc(commandBuffer: VkCommandBuffer, attachmentCount: uint32, pColorWriteEnables: ptr VkBool32): void {.stdcall.} +proc loadVK_EXT_color_write_enable*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdSetColorWriteEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, attachmentCount: uint32, pColorWriteEnables: ptr VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetColorWriteEnableEXT")) + +proc loadVK_SEC_amigo_profiling*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_NVX_binary_import +var + vkCreateCuModuleNVX*: proc(device: VkDevice, pCreateInfo: ptr VkCuModuleCreateInfoNVX, pAllocator: ptr VkAllocationCallbacks, pModule: ptr VkCuModuleNVX): VkResult {.stdcall.} + vkCreateCuFunctionNVX*: proc(device: VkDevice, pCreateInfo: ptr VkCuFunctionCreateInfoNVX, pAllocator: ptr VkAllocationCallbacks, pFunction: ptr VkCuFunctionNVX): VkResult {.stdcall.} + vkDestroyCuModuleNVX*: proc(device: VkDevice, module: VkCuModuleNVX, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkDestroyCuFunctionNVX*: proc(device: VkDevice, function: VkCuFunctionNVX, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCmdCuLaunchKernelNVX*: proc(commandBuffer: VkCommandBuffer, pLaunchInfo: ptr VkCuLaunchInfoNVX): void {.stdcall.} +proc loadVK_NVX_binary_import*(instance: VkInstance) = + vkCreateCuModuleNVX = cast[proc(device: VkDevice, pCreateInfo: ptr VkCuModuleCreateInfoNVX, pAllocator: ptr VkAllocationCallbacks, pModule: ptr VkCuModuleNVX): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateCuModuleNVX")) + vkCreateCuFunctionNVX = cast[proc(device: VkDevice, pCreateInfo: ptr VkCuFunctionCreateInfoNVX, pAllocator: ptr VkAllocationCallbacks, pFunction: ptr VkCuFunctionNVX): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateCuFunctionNVX")) + vkDestroyCuModuleNVX = cast[proc(device: VkDevice, module: VkCuModuleNVX, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyCuModuleNVX")) + vkDestroyCuFunctionNVX = cast[proc(device: VkDevice, function: VkCuFunctionNVX, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyCuFunctionNVX")) + vkCmdCuLaunchKernelNVX = cast[proc(commandBuffer: VkCommandBuffer, pLaunchInfo: ptr VkCuLaunchInfoNVX): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCuLaunchKernelNVX")) + +proc loadVK_NV_representative_fragment_test*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_EXT_validation_cache +var + vkCreateValidationCacheEXT*: proc(device: VkDevice, pCreateInfo: ptr VkValidationCacheCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pValidationCache: ptr VkValidationCacheEXT): VkResult {.stdcall.} + vkDestroyValidationCacheEXT*: proc(device: VkDevice, validationCache: VkValidationCacheEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkMergeValidationCachesEXT*: proc(device: VkDevice, dstCache: VkValidationCacheEXT, srcCacheCount: uint32, pSrcCaches: ptr VkValidationCacheEXT): VkResult {.stdcall.} + vkGetValidationCacheDataEXT*: proc(device: VkDevice, validationCache: VkValidationCacheEXT, pDataSize: ptr csize_t, pData: pointer): VkResult {.stdcall.} +proc loadVK_EXT_validation_cache*(instance: VkInstance) = + vkCreateValidationCacheEXT = cast[proc(device: VkDevice, pCreateInfo: ptr VkValidationCacheCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pValidationCache: ptr VkValidationCacheEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateValidationCacheEXT")) + vkDestroyValidationCacheEXT = cast[proc(device: VkDevice, validationCache: VkValidationCacheEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyValidationCacheEXT")) + vkMergeValidationCachesEXT = cast[proc(device: VkDevice, dstCache: VkValidationCacheEXT, srcCacheCount: uint32, pSrcCaches: ptr VkValidationCacheEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkMergeValidationCachesEXT")) + vkGetValidationCacheDataEXT = cast[proc(device: VkDevice, validationCache: VkValidationCacheEXT, pDataSize: ptr csize_t, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetValidationCacheDataEXT")) + +proc loadVK_NV_inherited_viewport_scissor*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_legacy_dithering*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_physical_device_drm*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_pipeline_protected_access*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_EXT_discard_rectangles +var + vkCmdSetDiscardRectangleEXT*: proc(commandBuffer: VkCommandBuffer, firstDiscardRectangle: uint32, discardRectangleCount: uint32, pDiscardRectangles: ptr VkRect2D): void {.stdcall.} + vkCmdSetDiscardRectangleEnableEXT*: proc(commandBuffer: VkCommandBuffer, discardRectangleEnable: VkBool32): void {.stdcall.} + vkCmdSetDiscardRectangleModeEXT*: proc(commandBuffer: VkCommandBuffer, discardRectangleMode: VkDiscardRectangleModeEXT): void {.stdcall.} +proc loadVK_EXT_discard_rectangles*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdSetDiscardRectangleEXT = cast[proc(commandBuffer: VkCommandBuffer, firstDiscardRectangle: uint32, discardRectangleCount: uint32, pDiscardRectangles: ptr VkRect2D): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDiscardRectangleEXT")) + vkCmdSetDiscardRectangleEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, discardRectangleEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDiscardRectangleEnableEXT")) + vkCmdSetDiscardRectangleModeEXT = cast[proc(commandBuffer: VkCommandBuffer, discardRectangleMode: VkDiscardRectangleModeEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDiscardRectangleModeEXT")) + +proc loadVK_EXT_shader_stencil_export*(instance: VkInstance) = + discard + +# extension VK_NV_external_memory_rdma +var + vkGetMemoryRemoteAddressNV*: proc(device: VkDevice, pMemoryGetRemoteAddressInfo: ptr VkMemoryGetRemoteAddressInfoNV, pAddress: ptr VkRemoteAddressNV): VkResult {.stdcall.} +proc loadVK_NV_external_memory_rdma*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetMemoryRemoteAddressNV = cast[proc(device: VkDevice, pMemoryGetRemoteAddressInfo: ptr VkMemoryGetRemoteAddressInfoNV, pAddress: ptr VkRemoteAddressNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryRemoteAddressNV")) + +proc loadVK_ARM_shader_core_builtins*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_QCOM_multiview_per_view_render_areas*(instance: VkInstance) = + discard + +proc loadVK_LUNARG_direct_driver_loading*(instance: VkInstance) = + discard + +proc loadVK_AMD_shader_explicit_vertex_parameter*(instance: VkInstance) = + discard + +# extension VK_EXT_headless_surface +var + vkCreateHeadlessSurfaceEXT*: proc(instance: VkInstance, pCreateInfo: ptr VkHeadlessSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} +proc loadVK_EXT_headless_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateHeadlessSurfaceEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkHeadlessSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT")) + +proc loadVK_NV_shader_sm_builtins*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_shader_subgroup_vote*(instance: VkInstance) = + discard + +# extension VK_NV_copy_memory_indirect +var + vkCmdCopyMemoryIndirectNV*: proc(commandBuffer: VkCommandBuffer, copyBufferAddress: VkDeviceAddress, copyCount: uint32, stride: uint32): void {.stdcall.} + vkCmdCopyMemoryToImageIndirectNV*: proc(commandBuffer: VkCommandBuffer, copyBufferAddress: VkDeviceAddress, copyCount: uint32, stride: uint32, dstImage: VkImage, dstImageLayout: VkImageLayout, pImageSubresources: ptr VkImageSubresourceLayers): void {.stdcall.} +proc loadVK_NV_copy_memory_indirect*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_2(instance) + vkCmdCopyMemoryIndirectNV = cast[proc(commandBuffer: VkCommandBuffer, copyBufferAddress: VkDeviceAddress, copyCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMemoryIndirectNV")) + vkCmdCopyMemoryToImageIndirectNV = cast[proc(commandBuffer: VkCommandBuffer, copyBufferAddress: VkDeviceAddress, copyCount: uint32, stride: uint32, dstImage: VkImage, dstImageLayout: VkImageLayout, pImageSubresources: ptr VkImageSubresourceLayers): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMemoryToImageIndirectNV")) + +proc loadVK_EXT_astc_decode_mode*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +# extension VK_KHR_get_surface_capabilities2 +var + vkGetPhysicalDeviceSurfaceCapabilities2KHR*: proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pSurfaceCapabilities: ptr VkSurfaceCapabilities2KHR): VkResult {.stdcall.} + vkGetPhysicalDeviceSurfaceFormats2KHR*: proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pSurfaceFormatCount: ptr uint32, pSurfaceFormats: ptr VkSurfaceFormat2KHR): VkResult {.stdcall.} +proc loadVK_KHR_get_surface_capabilities2*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkGetPhysicalDeviceSurfaceCapabilities2KHR = cast[proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pSurfaceCapabilities: ptr VkSurfaceCapabilities2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR")) + vkGetPhysicalDeviceSurfaceFormats2KHR = cast[proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pSurfaceFormatCount: ptr uint32, pSurfaceFormats: ptr VkSurfaceFormat2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormats2KHR")) + +# extension VK_HUAWEI_cluster_culling_shader +var + vkCmdDrawClusterHUAWEI*: proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.} + vkCmdDrawClusterIndirectHUAWEI*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize): void {.stdcall.} +proc loadVK_HUAWEI_cluster_culling_shader*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkCmdDrawClusterHUAWEI = cast[proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawClusterHUAWEI")) + vkCmdDrawClusterIndirectHUAWEI = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawClusterIndirectHUAWEI")) + +proc loadVK_KHR_surface_protected_capabilities*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_KHR_get_surface_capabilities2(instance) + +proc loadVK_NV_shader_image_footprint*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_NV_compute_shader_derivatives*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_QCOM_fragment_density_map_offset*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_EXT_fragment_density_map(instance) + +proc loadVK_EXT_shader_atomic_float2*(instance: VkInstance) = + loadVK_EXT_shader_atomic_float(instance) + +# extension VK_EXT_pageable_device_local_memory +var + vkSetDeviceMemoryPriorityEXT*: proc(device: VkDevice, memory: VkDeviceMemory, priority: float32): void {.stdcall.} +proc loadVK_EXT_pageable_device_local_memory*(instance: VkInstance) = + loadVK_EXT_memory_priority(instance) + vkSetDeviceMemoryPriorityEXT = cast[proc(device: VkDevice, memory: VkDeviceMemory, priority: float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetDeviceMemoryPriorityEXT")) + +# extension VK_KHR_swapchain +var + vkCreateSwapchainKHR*: proc(device: VkDevice, pCreateInfo: ptr VkSwapchainCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSwapchain: ptr VkSwapchainKHR): VkResult {.stdcall.} + vkDestroySwapchainKHR*: proc(device: VkDevice, swapchain: VkSwapchainKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetSwapchainImagesKHR*: proc(device: VkDevice, swapchain: VkSwapchainKHR, pSwapchainImageCount: ptr uint32, pSwapchainImages: ptr VkImage): VkResult {.stdcall.} + vkAcquireNextImageKHR*: proc(device: VkDevice, swapchain: VkSwapchainKHR, timeout: uint64, semaphore: VkSemaphore, fence: VkFence, pImageIndex: ptr uint32): VkResult {.stdcall.} + vkQueuePresentKHR*: proc(queue: VkQueue, pPresentInfo: ptr VkPresentInfoKHR): VkResult {.stdcall.} + vkGetDeviceGroupPresentCapabilitiesKHR*: proc(device: VkDevice, pDeviceGroupPresentCapabilities: ptr VkDeviceGroupPresentCapabilitiesKHR): VkResult {.stdcall.} + vkGetDeviceGroupSurfacePresentModesKHR*: proc(device: VkDevice, surface: VkSurfaceKHR, pModes: ptr VkDeviceGroupPresentModeFlagsKHR): VkResult {.stdcall.} + vkGetPhysicalDevicePresentRectanglesKHR*: proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pRectCount: ptr uint32, pRects: ptr VkRect2D): VkResult {.stdcall.} + vkAcquireNextImage2KHR*: proc(device: VkDevice, pAcquireInfo: ptr VkAcquireNextImageInfoKHR, pImageIndex: ptr uint32): VkResult {.stdcall.} +proc loadVK_KHR_swapchain*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateSwapchainKHR = cast[proc(device: VkDevice, pCreateInfo: ptr VkSwapchainCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSwapchain: ptr VkSwapchainKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateSwapchainKHR")) + vkDestroySwapchainKHR = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroySwapchainKHR")) + vkGetSwapchainImagesKHR = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, pSwapchainImageCount: ptr uint32, pSwapchainImages: ptr VkImage): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSwapchainImagesKHR")) + vkAcquireNextImageKHR = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, timeout: uint64, semaphore: VkSemaphore, fence: VkFence, pImageIndex: ptr uint32): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireNextImageKHR")) + vkQueuePresentKHR = cast[proc(queue: VkQueue, pPresentInfo: ptr VkPresentInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueuePresentKHR")) + vkGetDeviceGroupPresentCapabilitiesKHR = cast[proc(device: VkDevice, pDeviceGroupPresentCapabilities: ptr VkDeviceGroupPresentCapabilitiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceGroupPresentCapabilitiesKHR")) + vkGetDeviceGroupSurfacePresentModesKHR = cast[proc(device: VkDevice, surface: VkSurfaceKHR, pModes: ptr VkDeviceGroupPresentModeFlagsKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceGroupSurfacePresentModesKHR")) + vkGetPhysicalDevicePresentRectanglesKHR = cast[proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pRectCount: ptr uint32, pRects: ptr VkRect2D): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDevicePresentRectanglesKHR")) + vkAcquireNextImage2KHR = cast[proc(device: VkDevice, pAcquireInfo: ptr VkAcquireNextImageInfoKHR, pImageIndex: ptr uint32): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireNextImage2KHR")) + +proc loadVK_EXT_fragment_density_map2*(instance: VkInstance) = + loadVK_EXT_fragment_density_map(instance) + +# extension VK_NV_fragment_shading_rate_enums +var + vkCmdSetFragmentShadingRateEnumNV*: proc(commandBuffer: VkCommandBuffer, shadingRate: VkFragmentShadingRateNV, combinerOps: array[2, VkFragmentShadingRateCombinerOpKHR]): void {.stdcall.} +proc loadVK_NV_fragment_shading_rate_enums*(instance: VkInstance) = + loadVK_KHR_fragment_shading_rate(instance) + vkCmdSetFragmentShadingRateEnumNV = cast[proc(commandBuffer: VkCommandBuffer, shadingRate: VkFragmentShadingRateNV, combinerOps: array[2, VkFragmentShadingRateCombinerOpKHR]): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetFragmentShadingRateEnumNV")) + +# extension VK_AMD_display_native_hdr +var + vkSetLocalDimmingAMD*: proc(device: VkDevice, swapChain: VkSwapchainKHR, localDimmingEnable: VkBool32): void {.stdcall.} +proc loadVK_AMD_display_native_hdr*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_KHR_get_surface_capabilities2(instance) + loadVK_KHR_swapchain(instance) + vkSetLocalDimmingAMD = cast[proc(device: VkDevice, swapChain: VkSwapchainKHR, localDimmingEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetLocalDimmingAMD")) + +proc loadVK_NV_present_barrier*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_KHR_surface(instance) + loadVK_KHR_get_surface_capabilities2(instance) + loadVK_KHR_swapchain(instance) + +proc loadVK_QCOM_rotated_copy_commands*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + loadVK_VERSION_1_3(instance) + +proc loadVK_EXT_surface_maintenance1*(instance: VkInstance) = + loadVK_KHR_surface(instance) + loadVK_KHR_get_surface_capabilities2(instance) + +# extension VK_KHR_acceleration_structure +var + vkCreateAccelerationStructureKHR*: proc(device: VkDevice, pCreateInfo: ptr VkAccelerationStructureCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pAccelerationStructure: ptr VkAccelerationStructureKHR): VkResult {.stdcall.} + vkDestroyAccelerationStructureKHR*: proc(device: VkDevice, accelerationStructure: VkAccelerationStructureKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCmdBuildAccelerationStructuresKHR*: proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, ppBuildRangeInfos: ptr ptr VkAccelerationStructureBuildRangeInfoKHR): void {.stdcall.} + vkCmdBuildAccelerationStructuresIndirectKHR*: proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, pIndirectDeviceAddresses: ptr VkDeviceAddress, pIndirectStrides: ptr uint32, ppMaxPrimitiveCounts: ptr ptr uint32): void {.stdcall.} + vkBuildAccelerationStructuresKHR*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, ppBuildRangeInfos: ptr ptr VkAccelerationStructureBuildRangeInfoKHR): VkResult {.stdcall.} + vkCopyAccelerationStructureKHR*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyAccelerationStructureInfoKHR): VkResult {.stdcall.} + vkCopyAccelerationStructureToMemoryKHR*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyAccelerationStructureToMemoryInfoKHR): VkResult {.stdcall.} + vkCopyMemoryToAccelerationStructureKHR*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMemoryToAccelerationStructureInfoKHR): VkResult {.stdcall.} + vkWriteAccelerationStructuresPropertiesKHR*: proc(device: VkDevice, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureKHR, queryType: VkQueryType, dataSize: csize_t, pData: pointer, stride: csize_t): VkResult {.stdcall.} + vkCmdCopyAccelerationStructureKHR*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyAccelerationStructureInfoKHR): void {.stdcall.} + vkCmdCopyAccelerationStructureToMemoryKHR*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyAccelerationStructureToMemoryInfoKHR): void {.stdcall.} + vkCmdCopyMemoryToAccelerationStructureKHR*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMemoryToAccelerationStructureInfoKHR): void {.stdcall.} + vkGetAccelerationStructureDeviceAddressKHR*: proc(device: VkDevice, pInfo: ptr VkAccelerationStructureDeviceAddressInfoKHR): VkDeviceAddress {.stdcall.} + vkCmdWriteAccelerationStructuresPropertiesKHR*: proc(commandBuffer: VkCommandBuffer, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureKHR, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.} + vkGetDeviceAccelerationStructureCompatibilityKHR*: proc(device: VkDevice, pVersionInfo: ptr VkAccelerationStructureVersionInfoKHR, pCompatibility: ptr VkAccelerationStructureCompatibilityKHR): void {.stdcall.} + vkGetAccelerationStructureBuildSizesKHR*: proc(device: VkDevice, buildType: VkAccelerationStructureBuildTypeKHR, pBuildInfo: ptr VkAccelerationStructureBuildGeometryInfoKHR, pMaxPrimitiveCounts: ptr uint32, pSizeInfo: ptr VkAccelerationStructureBuildSizesInfoKHR): void {.stdcall.} +proc loadVK_KHR_acceleration_structure*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_2(instance) + loadVK_VERSION_1_2(instance) + loadVK_KHR_deferred_host_operations(instance) + vkCreateAccelerationStructureKHR = cast[proc(device: VkDevice, pCreateInfo: ptr VkAccelerationStructureCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pAccelerationStructure: ptr VkAccelerationStructureKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateAccelerationStructureKHR")) + vkDestroyAccelerationStructureKHR = cast[proc(device: VkDevice, accelerationStructure: VkAccelerationStructureKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyAccelerationStructureKHR")) + vkCmdBuildAccelerationStructuresKHR = cast[proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, ppBuildRangeInfos: ptr ptr VkAccelerationStructureBuildRangeInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBuildAccelerationStructuresKHR")) + vkCmdBuildAccelerationStructuresIndirectKHR = cast[proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, pIndirectDeviceAddresses: ptr VkDeviceAddress, pIndirectStrides: ptr uint32, ppMaxPrimitiveCounts: ptr ptr uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBuildAccelerationStructuresIndirectKHR")) + vkBuildAccelerationStructuresKHR = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, ppBuildRangeInfos: ptr ptr VkAccelerationStructureBuildRangeInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBuildAccelerationStructuresKHR")) + vkCopyAccelerationStructureKHR = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyAccelerationStructureInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyAccelerationStructureKHR")) + vkCopyAccelerationStructureToMemoryKHR = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyAccelerationStructureToMemoryInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyAccelerationStructureToMemoryKHR")) + vkCopyMemoryToAccelerationStructureKHR = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMemoryToAccelerationStructureInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyMemoryToAccelerationStructureKHR")) + vkWriteAccelerationStructuresPropertiesKHR = cast[proc(device: VkDevice, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureKHR, queryType: VkQueryType, dataSize: csize_t, pData: pointer, stride: csize_t): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkWriteAccelerationStructuresPropertiesKHR")) + vkCmdCopyAccelerationStructureKHR = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyAccelerationStructureInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyAccelerationStructureKHR")) + vkCmdCopyAccelerationStructureToMemoryKHR = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyAccelerationStructureToMemoryInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyAccelerationStructureToMemoryKHR")) + vkCmdCopyMemoryToAccelerationStructureKHR = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMemoryToAccelerationStructureInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMemoryToAccelerationStructureKHR")) + vkGetAccelerationStructureDeviceAddressKHR = cast[proc(device: VkDevice, pInfo: ptr VkAccelerationStructureDeviceAddressInfoKHR): VkDeviceAddress {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureDeviceAddressKHR")) + vkCmdWriteAccelerationStructuresPropertiesKHR = cast[proc(commandBuffer: VkCommandBuffer, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureKHR, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteAccelerationStructuresPropertiesKHR")) + vkGetDeviceAccelerationStructureCompatibilityKHR = cast[proc(device: VkDevice, pVersionInfo: ptr VkAccelerationStructureVersionInfoKHR, pCompatibility: ptr VkAccelerationStructureCompatibilityKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceAccelerationStructureCompatibilityKHR")) + vkGetAccelerationStructureBuildSizesKHR = cast[proc(device: VkDevice, buildType: VkAccelerationStructureBuildTypeKHR, pBuildInfo: ptr VkAccelerationStructureBuildGeometryInfoKHR, pMaxPrimitiveCounts: ptr uint32, pSizeInfo: ptr VkAccelerationStructureBuildSizesInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureBuildSizesKHR")) + +# extension VK_GOOGLE_display_timing +var + vkGetRefreshCycleDurationGOOGLE*: proc(device: VkDevice, swapchain: VkSwapchainKHR, pDisplayTimingProperties: ptr VkRefreshCycleDurationGOOGLE): VkResult {.stdcall.} + vkGetPastPresentationTimingGOOGLE*: proc(device: VkDevice, swapchain: VkSwapchainKHR, pPresentationTimingCount: ptr uint32, pPresentationTimings: ptr VkPastPresentationTimingGOOGLE): VkResult {.stdcall.} +proc loadVK_GOOGLE_display_timing*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + vkGetRefreshCycleDurationGOOGLE = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, pDisplayTimingProperties: ptr VkRefreshCycleDurationGOOGLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRefreshCycleDurationGOOGLE")) + vkGetPastPresentationTimingGOOGLE = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, pPresentationTimingCount: ptr uint32, pPresentationTimings: ptr VkPastPresentationTimingGOOGLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPastPresentationTimingGOOGLE")) + +proc loadVK_QCOM_render_pass_transform*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + loadVK_KHR_surface(instance) + +proc loadVK_GOOGLE_surfaceless_query*(instance: VkInstance) = + loadVK_KHR_surface(instance) + +proc loadVK_EXT_image_compression_control_swapchain*(instance: VkInstance) = + loadVK_EXT_image_compression_control(instance) + +# extension VK_KHR_display +var + vkGetPhysicalDeviceDisplayPropertiesKHR*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPropertiesKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceDisplayPlanePropertiesKHR*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPlanePropertiesKHR): VkResult {.stdcall.} + vkGetDisplayPlaneSupportedDisplaysKHR*: proc(physicalDevice: VkPhysicalDevice, planeIndex: uint32, pDisplayCount: ptr uint32, pDisplays: ptr VkDisplayKHR): VkResult {.stdcall.} + vkGetDisplayModePropertiesKHR*: proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayModePropertiesKHR): VkResult {.stdcall.} + vkCreateDisplayModeKHR*: proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pCreateInfo: ptr VkDisplayModeCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pMode: ptr VkDisplayModeKHR): VkResult {.stdcall.} + vkGetDisplayPlaneCapabilitiesKHR*: proc(physicalDevice: VkPhysicalDevice, mode: VkDisplayModeKHR, planeIndex: uint32, pCapabilities: ptr VkDisplayPlaneCapabilitiesKHR): VkResult {.stdcall.} + vkCreateDisplayPlaneSurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkDisplaySurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} +proc loadVK_KHR_display*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkGetPhysicalDeviceDisplayPropertiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR")) + vkGetPhysicalDeviceDisplayPlanePropertiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPlanePropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR")) + vkGetDisplayPlaneSupportedDisplaysKHR = cast[proc(physicalDevice: VkPhysicalDevice, planeIndex: uint32, pDisplayCount: ptr uint32, pDisplays: ptr VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR")) + vkGetDisplayModePropertiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayModePropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR")) + vkCreateDisplayModeKHR = cast[proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pCreateInfo: ptr VkDisplayModeCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pMode: ptr VkDisplayModeKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDisplayModeKHR")) + vkGetDisplayPlaneCapabilitiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, mode: VkDisplayModeKHR, planeIndex: uint32, pCapabilities: ptr VkDisplayPlaneCapabilitiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR")) + vkCreateDisplayPlaneSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDisplaySurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDisplayPlaneSurfaceKHR")) + +# extension VK_EXT_swapchain_maintenance1 +var + vkReleaseSwapchainImagesEXT*: proc(device: VkDevice, pReleaseInfo: ptr VkReleaseSwapchainImagesInfoEXT): VkResult {.stdcall.} +proc loadVK_EXT_swapchain_maintenance1*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + loadVK_EXT_surface_maintenance1(instance) + loadVK_VERSION_1_1(instance) + vkReleaseSwapchainImagesEXT = cast[proc(device: VkDevice, pReleaseInfo: ptr VkReleaseSwapchainImagesInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkReleaseSwapchainImagesEXT")) + +# extension VK_EXT_direct_mode_display +var + vkReleaseDisplayEXT*: proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR): VkResult {.stdcall.} +proc loadVK_EXT_direct_mode_display*(instance: VkInstance) = + loadVK_KHR_display(instance) + vkReleaseDisplayEXT = cast[proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkReleaseDisplayEXT")) + +proc loadVK_KHR_swapchain_mutable_format*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_2(instance) + +proc loadVK_EXT_swapchain_colorspace*(instance: VkInstance) = + loadVK_KHR_surface(instance) + +# extension VK_EXT_opacity_micromap +var + vkCreateMicromapEXT*: proc(device: VkDevice, pCreateInfo: ptr VkMicromapCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pMicromap: ptr VkMicromapEXT): VkResult {.stdcall.} + vkDestroyMicromapEXT*: proc(device: VkDevice, micromap: VkMicromapEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCmdBuildMicromapsEXT*: proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkMicromapBuildInfoEXT): void {.stdcall.} + vkBuildMicromapsEXT*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, infoCount: uint32, pInfos: ptr VkMicromapBuildInfoEXT): VkResult {.stdcall.} + vkCopyMicromapEXT*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMicromapInfoEXT): VkResult {.stdcall.} + vkCopyMicromapToMemoryEXT*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMicromapToMemoryInfoEXT): VkResult {.stdcall.} + vkCopyMemoryToMicromapEXT*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMemoryToMicromapInfoEXT): VkResult {.stdcall.} + vkWriteMicromapsPropertiesEXT*: proc(device: VkDevice, micromapCount: uint32, pMicromaps: ptr VkMicromapEXT, queryType: VkQueryType, dataSize: csize_t, pData: pointer, stride: csize_t): VkResult {.stdcall.} + vkCmdCopyMicromapEXT*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMicromapInfoEXT): void {.stdcall.} + vkCmdCopyMicromapToMemoryEXT*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMicromapToMemoryInfoEXT): void {.stdcall.} + vkCmdCopyMemoryToMicromapEXT*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMemoryToMicromapInfoEXT): void {.stdcall.} + vkCmdWriteMicromapsPropertiesEXT*: proc(commandBuffer: VkCommandBuffer, micromapCount: uint32, pMicromaps: ptr VkMicromapEXT, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.} + vkGetDeviceMicromapCompatibilityEXT*: proc(device: VkDevice, pVersionInfo: ptr VkMicromapVersionInfoEXT, pCompatibility: ptr VkAccelerationStructureCompatibilityKHR): void {.stdcall.} + vkGetMicromapBuildSizesEXT*: proc(device: VkDevice, buildType: VkAccelerationStructureBuildTypeKHR, pBuildInfo: ptr VkMicromapBuildInfoEXT, pSizeInfo: ptr VkMicromapBuildSizesInfoEXT): void {.stdcall.} +proc loadVK_EXT_opacity_micromap*(instance: VkInstance) = + loadVK_KHR_acceleration_structure(instance) + loadVK_VERSION_1_3(instance) + vkCreateMicromapEXT = cast[proc(device: VkDevice, pCreateInfo: ptr VkMicromapCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pMicromap: ptr VkMicromapEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateMicromapEXT")) + vkDestroyMicromapEXT = cast[proc(device: VkDevice, micromap: VkMicromapEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyMicromapEXT")) + vkCmdBuildMicromapsEXT = cast[proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkMicromapBuildInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBuildMicromapsEXT")) + vkBuildMicromapsEXT = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, infoCount: uint32, pInfos: ptr VkMicromapBuildInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBuildMicromapsEXT")) + vkCopyMicromapEXT = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMicromapInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyMicromapEXT")) + vkCopyMicromapToMemoryEXT = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMicromapToMemoryInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyMicromapToMemoryEXT")) + vkCopyMemoryToMicromapEXT = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMemoryToMicromapInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyMemoryToMicromapEXT")) + vkWriteMicromapsPropertiesEXT = cast[proc(device: VkDevice, micromapCount: uint32, pMicromaps: ptr VkMicromapEXT, queryType: VkQueryType, dataSize: csize_t, pData: pointer, stride: csize_t): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkWriteMicromapsPropertiesEXT")) + vkCmdCopyMicromapEXT = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMicromapInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMicromapEXT")) + vkCmdCopyMicromapToMemoryEXT = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMicromapToMemoryInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMicromapToMemoryEXT")) + vkCmdCopyMemoryToMicromapEXT = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMemoryToMicromapInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMemoryToMicromapEXT")) + vkCmdWriteMicromapsPropertiesEXT = cast[proc(commandBuffer: VkCommandBuffer, micromapCount: uint32, pMicromaps: ptr VkMicromapEXT, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteMicromapsPropertiesEXT")) + vkGetDeviceMicromapCompatibilityEXT = cast[proc(device: VkDevice, pVersionInfo: ptr VkMicromapVersionInfoEXT, pCompatibility: ptr VkAccelerationStructureCompatibilityKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceMicromapCompatibilityEXT")) + vkGetMicromapBuildSizesEXT = cast[proc(device: VkDevice, buildType: VkAccelerationStructureBuildTypeKHR, pBuildInfo: ptr VkMicromapBuildInfoEXT, pSizeInfo: ptr VkMicromapBuildSizesInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMicromapBuildSizesEXT")) + +proc loadVK_KHR_incremental_present*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + +# extension VK_KHR_shared_presentable_image +var + vkGetSwapchainStatusKHR*: proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.} +proc loadVK_KHR_shared_presentable_image*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + loadVK_VERSION_1_1(instance) + loadVK_KHR_get_surface_capabilities2(instance) + vkGetSwapchainStatusKHR = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSwapchainStatusKHR")) + +# extension VK_EXT_hdr_metadata +var + vkSetHdrMetadataEXT*: proc(device: VkDevice, swapchainCount: uint32, pSwapchains: ptr VkSwapchainKHR, pMetadata: ptr VkHdrMetadataEXT): void {.stdcall.} +proc loadVK_EXT_hdr_metadata*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + vkSetHdrMetadataEXT = cast[proc(device: VkDevice, swapchainCount: uint32, pSwapchains: ptr VkSwapchainKHR, pMetadata: ptr VkHdrMetadataEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetHdrMetadataEXT")) + +proc loadVK_KHR_present_id*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + loadVK_VERSION_1_1(instance) + +# extension VK_KHR_ray_tracing_maintenance1 +var + vkCmdTraceRaysIndirect2KHR*: proc(commandBuffer: VkCommandBuffer, indirectDeviceAddress: VkDeviceAddress): void {.stdcall.} +proc loadVK_KHR_ray_tracing_maintenance1*(instance: VkInstance) = + loadVK_KHR_acceleration_structure(instance) + vkCmdTraceRaysIndirect2KHR = cast[proc(commandBuffer: VkCommandBuffer, indirectDeviceAddress: VkDeviceAddress): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdTraceRaysIndirect2KHR")) + +# extension VK_KHR_ray_tracing_pipeline +var + vkCmdTraceRaysKHR*: proc(commandBuffer: VkCommandBuffer, pRaygenShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pMissShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pHitShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pCallableShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, width: uint32, height: uint32, depth: uint32): void {.stdcall.} + vkCreateRayTracingPipelinesKHR*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkRayTracingPipelineCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.} + vkGetRayTracingShaderGroupHandlesKHR*: proc(device: VkDevice, pipeline: VkPipeline, firstGroup: uint32, groupCount: uint32, dataSize: csize_t, pData: pointer): VkResult {.stdcall.} + vkGetRayTracingCaptureReplayShaderGroupHandlesKHR*: proc(device: VkDevice, pipeline: VkPipeline, firstGroup: uint32, groupCount: uint32, dataSize: csize_t, pData: pointer): VkResult {.stdcall.} + vkCmdTraceRaysIndirectKHR*: proc(commandBuffer: VkCommandBuffer, pRaygenShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pMissShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pHitShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pCallableShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, indirectDeviceAddress: VkDeviceAddress): void {.stdcall.} + vkGetRayTracingShaderGroupStackSizeKHR*: proc(device: VkDevice, pipeline: VkPipeline, group: uint32, groupShader: VkShaderGroupShaderKHR): VkDeviceSize {.stdcall.} + vkCmdSetRayTracingPipelineStackSizeKHR*: proc(commandBuffer: VkCommandBuffer, pipelineStackSize: uint32): void {.stdcall.} +proc loadVK_KHR_ray_tracing_pipeline*(instance: VkInstance) = + loadVK_VERSION_1_2(instance) + loadVK_KHR_acceleration_structure(instance) + vkCmdTraceRaysKHR = cast[proc(commandBuffer: VkCommandBuffer, pRaygenShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pMissShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pHitShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pCallableShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, width: uint32, height: uint32, depth: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdTraceRaysKHR")) + vkCreateRayTracingPipelinesKHR = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkRayTracingPipelineCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateRayTracingPipelinesKHR")) + vkGetRayTracingShaderGroupHandlesKHR = cast[proc(device: VkDevice, pipeline: VkPipeline, firstGroup: uint32, groupCount: uint32, dataSize: csize_t, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRayTracingShaderGroupHandlesKHR")) + vkGetRayTracingCaptureReplayShaderGroupHandlesKHR = cast[proc(device: VkDevice, pipeline: VkPipeline, firstGroup: uint32, groupCount: uint32, dataSize: csize_t, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR")) + vkCmdTraceRaysIndirectKHR = cast[proc(commandBuffer: VkCommandBuffer, pRaygenShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pMissShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pHitShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pCallableShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, indirectDeviceAddress: VkDeviceAddress): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdTraceRaysIndirectKHR")) + vkGetRayTracingShaderGroupStackSizeKHR = cast[proc(device: VkDevice, pipeline: VkPipeline, group: uint32, groupShader: VkShaderGroupShaderKHR): VkDeviceSize {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRayTracingShaderGroupStackSizeKHR")) + vkCmdSetRayTracingPipelineStackSizeKHR = cast[proc(commandBuffer: VkCommandBuffer, pipelineStackSize: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetRayTracingPipelineStackSizeKHR")) + +# extension VK_HUAWEI_invocation_mask +var + vkCmdBindInvocationMaskHUAWEI*: proc(commandBuffer: VkCommandBuffer, imageView: VkImageView, imageLayout: VkImageLayout): void {.stdcall.} +proc loadVK_HUAWEI_invocation_mask*(instance: VkInstance) = + loadVK_KHR_ray_tracing_pipeline(instance) + loadVK_VERSION_1_3(instance) + vkCmdBindInvocationMaskHUAWEI = cast[proc(commandBuffer: VkCommandBuffer, imageView: VkImageView, imageLayout: VkImageLayout): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindInvocationMaskHUAWEI")) + +# extension VK_EXT_display_surface_counter +var + vkGetPhysicalDeviceSurfaceCapabilities2EXT*: proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceCapabilities: ptr VkSurfaceCapabilities2EXT): VkResult {.stdcall.} +proc loadVK_EXT_display_surface_counter*(instance: VkInstance) = + loadVK_KHR_display(instance) + vkGetPhysicalDeviceSurfaceCapabilities2EXT = cast[proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceCapabilities: ptr VkSurfaceCapabilities2EXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2EXT")) + +# extension VK_KHR_get_display_properties2 +var + vkGetPhysicalDeviceDisplayProperties2KHR*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayProperties2KHR): VkResult {.stdcall.} + vkGetPhysicalDeviceDisplayPlaneProperties2KHR*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPlaneProperties2KHR): VkResult {.stdcall.} + vkGetDisplayModeProperties2KHR*: proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayModeProperties2KHR): VkResult {.stdcall.} + vkGetDisplayPlaneCapabilities2KHR*: proc(physicalDevice: VkPhysicalDevice, pDisplayPlaneInfo: ptr VkDisplayPlaneInfo2KHR, pCapabilities: ptr VkDisplayPlaneCapabilities2KHR): VkResult {.stdcall.} +proc loadVK_KHR_get_display_properties2*(instance: VkInstance) = + loadVK_KHR_display(instance) + vkGetPhysicalDeviceDisplayProperties2KHR = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayProperties2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayProperties2KHR")) + vkGetPhysicalDeviceDisplayPlaneProperties2KHR = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPlaneProperties2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR")) + vkGetDisplayModeProperties2KHR = cast[proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayModeProperties2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDisplayModeProperties2KHR")) + vkGetDisplayPlaneCapabilities2KHR = cast[proc(physicalDevice: VkPhysicalDevice, pDisplayPlaneInfo: ptr VkDisplayPlaneInfo2KHR, pCapabilities: ptr VkDisplayPlaneCapabilities2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilities2KHR")) + +proc loadVK_KHR_ray_query*(instance: VkInstance) = + loadVK_VERSION_1_2(instance) + loadVK_KHR_acceleration_structure(instance) + +# extension VK_KHR_display_swapchain +var + vkCreateSharedSwapchainsKHR*: proc(device: VkDevice, swapchainCount: uint32, pCreateInfos: ptr VkSwapchainCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSwapchains: ptr VkSwapchainKHR): VkResult {.stdcall.} +proc loadVK_KHR_display_swapchain*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + loadVK_KHR_display(instance) + vkCreateSharedSwapchainsKHR = cast[proc(device: VkDevice, swapchainCount: uint32, pCreateInfos: ptr VkSwapchainCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSwapchains: ptr VkSwapchainKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateSharedSwapchainsKHR")) + +# extension VK_EXT_acquire_drm_display +var + vkAcquireDrmDisplayEXT*: proc(physicalDevice: VkPhysicalDevice, drmFd: int32, display: VkDisplayKHR): VkResult {.stdcall.} + vkGetDrmDisplayEXT*: proc(physicalDevice: VkPhysicalDevice, drmFd: int32, connectorId: uint32, display: ptr VkDisplayKHR): VkResult {.stdcall.} +proc loadVK_EXT_acquire_drm_display*(instance: VkInstance) = + loadVK_EXT_direct_mode_display(instance) + vkAcquireDrmDisplayEXT = cast[proc(physicalDevice: VkPhysicalDevice, drmFd: int32, display: VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireDrmDisplayEXT")) + vkGetDrmDisplayEXT = cast[proc(physicalDevice: VkPhysicalDevice, drmFd: int32, connectorId: uint32, display: ptr VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDrmDisplayEXT")) + +# extension VK_EXT_display_control +var + vkDisplayPowerControlEXT*: proc(device: VkDevice, display: VkDisplayKHR, pDisplayPowerInfo: ptr VkDisplayPowerInfoEXT): VkResult {.stdcall.} + vkRegisterDeviceEventEXT*: proc(device: VkDevice, pDeviceEventInfo: ptr VkDeviceEventInfoEXT, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.} + vkRegisterDisplayEventEXT*: proc(device: VkDevice, display: VkDisplayKHR, pDisplayEventInfo: ptr VkDisplayEventInfoEXT, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.} + vkGetSwapchainCounterEXT*: proc(device: VkDevice, swapchain: VkSwapchainKHR, counter: VkSurfaceCounterFlagBitsEXT, pCounterValue: ptr uint64): VkResult {.stdcall.} +proc loadVK_EXT_display_control*(instance: VkInstance) = + loadVK_EXT_display_surface_counter(instance) + loadVK_KHR_swapchain(instance) + vkDisplayPowerControlEXT = cast[proc(device: VkDevice, display: VkDisplayKHR, pDisplayPowerInfo: ptr VkDisplayPowerInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDisplayPowerControlEXT")) + vkRegisterDeviceEventEXT = cast[proc(device: VkDevice, pDeviceEventInfo: ptr VkDeviceEventInfoEXT, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkRegisterDeviceEventEXT")) + vkRegisterDisplayEventEXT = cast[proc(device: VkDevice, display: VkDisplayKHR, pDisplayEventInfo: ptr VkDisplayEventInfoEXT, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkRegisterDisplayEventEXT")) + vkGetSwapchainCounterEXT = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, counter: VkSurfaceCounterFlagBitsEXT, pCounterValue: ptr uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSwapchainCounterEXT")) + +proc loadVK_NV_ray_tracing_motion_blur*(instance: VkInstance) = + loadVK_KHR_ray_tracing_pipeline(instance) + +proc loadVK_EXT_pipeline_library_group_handles*(instance: VkInstance) = + loadVK_KHR_ray_tracing_pipeline(instance) + loadVK_KHR_pipeline_library(instance) + +# extension VK_NV_ray_tracing +var + vkCreateAccelerationStructureNV*: proc(device: VkDevice, pCreateInfo: ptr VkAccelerationStructureCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pAccelerationStructure: ptr VkAccelerationStructureNV): VkResult {.stdcall.} + vkDestroyAccelerationStructureNV*: proc(device: VkDevice, accelerationStructure: VkAccelerationStructureNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetAccelerationStructureMemoryRequirementsNV*: proc(device: VkDevice, pInfo: ptr VkAccelerationStructureMemoryRequirementsInfoNV, pMemoryRequirements: ptr VkMemoryRequirements2KHR): void {.stdcall.} + vkBindAccelerationStructureMemoryNV*: proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindAccelerationStructureMemoryInfoNV): VkResult {.stdcall.} + vkCmdBuildAccelerationStructureNV*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkAccelerationStructureInfoNV, instanceData: VkBuffer, instanceOffset: VkDeviceSize, update: VkBool32, dst: VkAccelerationStructureNV, src: VkAccelerationStructureNV, scratch: VkBuffer, scratchOffset: VkDeviceSize): void {.stdcall.} + vkCmdCopyAccelerationStructureNV*: proc(commandBuffer: VkCommandBuffer, dst: VkAccelerationStructureNV, src: VkAccelerationStructureNV, mode: VkCopyAccelerationStructureModeKHR): void {.stdcall.} + vkCmdTraceRaysNV*: proc(commandBuffer: VkCommandBuffer, raygenShaderBindingTableBuffer: VkBuffer, raygenShaderBindingOffset: VkDeviceSize, missShaderBindingTableBuffer: VkBuffer, missShaderBindingOffset: VkDeviceSize, missShaderBindingStride: VkDeviceSize, hitShaderBindingTableBuffer: VkBuffer, hitShaderBindingOffset: VkDeviceSize, hitShaderBindingStride: VkDeviceSize, callableShaderBindingTableBuffer: VkBuffer, callableShaderBindingOffset: VkDeviceSize, callableShaderBindingStride: VkDeviceSize, width: uint32, height: uint32, depth: uint32): void {.stdcall.} + vkCreateRayTracingPipelinesNV*: proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkRayTracingPipelineCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.} + vkGetRayTracingShaderGroupHandlesNV*: proc(device: VkDevice, pipeline: VkPipeline, firstGroup: uint32, groupCount: uint32, dataSize: csize_t, pData: pointer): VkResult {.stdcall.} + vkGetAccelerationStructureHandleNV*: proc(device: VkDevice, accelerationStructure: VkAccelerationStructureNV, dataSize: csize_t, pData: pointer): VkResult {.stdcall.} + vkCmdWriteAccelerationStructuresPropertiesNV*: proc(commandBuffer: VkCommandBuffer, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureNV, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.} + vkCompileDeferredNV*: proc(device: VkDevice, pipeline: VkPipeline, shader: uint32): VkResult {.stdcall.} +proc loadVK_NV_ray_tracing*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_1(instance) + vkCreateAccelerationStructureNV = cast[proc(device: VkDevice, pCreateInfo: ptr VkAccelerationStructureCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pAccelerationStructure: ptr VkAccelerationStructureNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateAccelerationStructureNV")) + vkDestroyAccelerationStructureNV = cast[proc(device: VkDevice, accelerationStructure: VkAccelerationStructureNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyAccelerationStructureNV")) + vkGetAccelerationStructureMemoryRequirementsNV = cast[proc(device: VkDevice, pInfo: ptr VkAccelerationStructureMemoryRequirementsInfoNV, pMemoryRequirements: ptr VkMemoryRequirements2KHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureMemoryRequirementsNV")) + vkBindAccelerationStructureMemoryNV = cast[proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindAccelerationStructureMemoryInfoNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindAccelerationStructureMemoryNV")) + vkCmdBuildAccelerationStructureNV = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkAccelerationStructureInfoNV, instanceData: VkBuffer, instanceOffset: VkDeviceSize, update: VkBool32, dst: VkAccelerationStructureNV, src: VkAccelerationStructureNV, scratch: VkBuffer, scratchOffset: VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBuildAccelerationStructureNV")) + vkCmdCopyAccelerationStructureNV = cast[proc(commandBuffer: VkCommandBuffer, dst: VkAccelerationStructureNV, src: VkAccelerationStructureNV, mode: VkCopyAccelerationStructureModeKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyAccelerationStructureNV")) + vkCmdTraceRaysNV = cast[proc(commandBuffer: VkCommandBuffer, raygenShaderBindingTableBuffer: VkBuffer, raygenShaderBindingOffset: VkDeviceSize, missShaderBindingTableBuffer: VkBuffer, missShaderBindingOffset: VkDeviceSize, missShaderBindingStride: VkDeviceSize, hitShaderBindingTableBuffer: VkBuffer, hitShaderBindingOffset: VkDeviceSize, hitShaderBindingStride: VkDeviceSize, callableShaderBindingTableBuffer: VkBuffer, callableShaderBindingOffset: VkDeviceSize, callableShaderBindingStride: VkDeviceSize, width: uint32, height: uint32, depth: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdTraceRaysNV")) + vkCreateRayTracingPipelinesNV = cast[proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkRayTracingPipelineCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateRayTracingPipelinesNV")) + vkGetRayTracingShaderGroupHandlesNV = vkGetRayTracingShaderGroupHandlesKHR + vkGetAccelerationStructureHandleNV = cast[proc(device: VkDevice, accelerationStructure: VkAccelerationStructureNV, dataSize: csize_t, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureHandleNV")) + vkCmdWriteAccelerationStructuresPropertiesNV = cast[proc(commandBuffer: VkCommandBuffer, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureNV, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteAccelerationStructuresPropertiesNV")) + vkCompileDeferredNV = cast[proc(device: VkDevice, pipeline: VkPipeline, shader: uint32): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCompileDeferredNV")) + +# extension VK_KHR_present_wait +var + vkWaitForPresentKHR*: proc(device: VkDevice, swapchain: VkSwapchainKHR, presentId: uint64, timeout: uint64): VkResult {.stdcall.} +proc loadVK_KHR_present_wait*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + loadVK_KHR_present_id(instance) + vkWaitForPresentKHR = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, presentId: uint64, timeout: uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkWaitForPresentKHR")) + +proc loadVK_NV_ray_tracing_invocation_reorder*(instance: VkInstance) = + loadVK_KHR_ray_tracing_pipeline(instance) + +var EXTENSION_LOADERS = { + "VK_NV_optical_flow": loadVK_NV_optical_flow, + "VK_EXT_vertex_attribute_divisor": loadVK_EXT_vertex_attribute_divisor, + "VK_EXT_pipeline_library_group_handles": loadVK_EXT_pipeline_library_group_handles, + "VK_NV_geometry_shader_passthrough": loadVK_NV_geometry_shader_passthrough, + "VK_EXT_line_rasterization": loadVK_EXT_line_rasterization, + "VK_EXT_rasterization_order_attachment_access": loadVK_EXT_rasterization_order_attachment_access, + "VK_EXT_shader_atomic_float2": loadVK_EXT_shader_atomic_float2, + "VK_IMG_format_pvrtc": loadVK_IMG_format_pvrtc, + "VK_AMD_texture_gather_bias_lod": loadVK_AMD_texture_gather_bias_lod, + "VK_KHR_shader_subgroup_uniform_control_flow": loadVK_KHR_shader_subgroup_uniform_control_flow, + "VK_AMD_shader_fragment_mask": loadVK_AMD_shader_fragment_mask, + "VK_EXT_external_memory_dma_buf": loadVK_EXT_external_memory_dma_buf, + "VK_IMG_filter_cubic": loadVK_IMG_filter_cubic, + "VK_EXT_pageable_device_local_memory": loadVK_EXT_pageable_device_local_memory, + "VK_EXT_primitive_topology_list_restart": loadVK_EXT_primitive_topology_list_restart, + "VK_KHR_global_priority": loadVK_KHR_global_priority, + "VK_AMD_shader_ballot": loadVK_AMD_shader_ballot, + "VK_AMD_buffer_marker": loadVK_AMD_buffer_marker, + "VK_NV_corner_sampled_image": loadVK_NV_corner_sampled_image, + "VK_NV_ray_tracing_invocation_reorder": loadVK_NV_ray_tracing_invocation_reorder, + "VK_QCOM_image_processing": loadVK_QCOM_image_processing, + "VK_AMD_shader_info": loadVK_AMD_shader_info, + "VK_KHR_pipeline_library": loadVK_KHR_pipeline_library, + "VK_EXT_blend_operation_advanced": loadVK_EXT_blend_operation_advanced, + "VK_AMD_gpu_shader_int16": loadVK_AMD_gpu_shader_int16, + "VK_EXT_pipeline_robustness": loadVK_EXT_pipeline_robustness, + "VK_NV_scissor_exclusive": loadVK_NV_scissor_exclusive, + "VK_EXT_sample_locations": loadVK_EXT_sample_locations, + "VK_NV_framebuffer_mixed_samples": loadVK_NV_framebuffer_mixed_samples, + "VK_NV_sample_mask_override_coverage": loadVK_NV_sample_mask_override_coverage, + "VK_KHR_present_id": loadVK_KHR_present_id, + "VK_EXT_descriptor_buffer": loadVK_EXT_descriptor_buffer, + "VK_EXT_filter_cubic": loadVK_EXT_filter_cubic, + "VK_KHR_pipeline_executable_properties": loadVK_KHR_pipeline_executable_properties, + "VK_EXT_extended_dynamic_state3": loadVK_EXT_extended_dynamic_state3, + "VK_KHR_performance_query": loadVK_KHR_performance_query, + "VK_GOOGLE_user_type": loadVK_GOOGLE_user_type, + "VK_KHR_ray_tracing_maintenance1": loadVK_KHR_ray_tracing_maintenance1, + "VK_EXT_debug_report": loadVK_EXT_debug_report, + "VK_EXT_multisampled_render_to_single_sampled": loadVK_EXT_multisampled_render_to_single_sampled, + "VK_EXT_device_address_binding_report": loadVK_EXT_device_address_binding_report, + "VK_NV_clip_space_w_scaling": loadVK_NV_clip_space_w_scaling, + "VK_NV_fill_rectangle": loadVK_NV_fill_rectangle, + "VK_EXT_shader_image_atomic_int64": loadVK_EXT_shader_image_atomic_int64, + "VK_KHR_swapchain": loadVK_KHR_swapchain, + "VK_NV_ray_tracing": loadVK_NV_ray_tracing, + "VK_EXT_swapchain_maintenance1": loadVK_EXT_swapchain_maintenance1, + "VK_KHR_ray_tracing_pipeline": loadVK_KHR_ray_tracing_pipeline, + "VK_EXT_ycbcr_image_arrays": loadVK_EXT_ycbcr_image_arrays, + "VK_AMD_negative_viewport_height": loadVK_AMD_negative_viewport_height, + "VK_EXT_provoking_vertex": loadVK_EXT_provoking_vertex, + "VK_EXT_calibrated_timestamps": loadVK_EXT_calibrated_timestamps, + "VK_EXT_attachment_feedback_loop_layout": loadVK_EXT_attachment_feedback_loop_layout, + "VK_AMD_mixed_attachment_samples": loadVK_AMD_mixed_attachment_samples, + "VK_HUAWEI_invocation_mask": loadVK_HUAWEI_invocation_mask, + "VK_EXT_external_memory_host": loadVK_EXT_external_memory_host, + "VK_NV_device_diagnostics_config": loadVK_NV_device_diagnostics_config, + "VK_EXT_fragment_density_map2": loadVK_EXT_fragment_density_map2, + "VK_NV_shader_subgroup_partitioned": loadVK_NV_shader_subgroup_partitioned, + "VK_EXT_image_sliced_view_of_3d": loadVK_EXT_image_sliced_view_of_3d, + "VK_NV_fragment_shading_rate_enums": loadVK_NV_fragment_shading_rate_enums, + "VK_EXT_display_surface_counter": loadVK_EXT_display_surface_counter, + "VK_ARM_shader_core_properties": loadVK_ARM_shader_core_properties, + "VK_EXT_shader_module_identifier": loadVK_EXT_shader_module_identifier, + "VK_EXT_border_color_swizzle": loadVK_EXT_border_color_swizzle, + "VK_AMD_shader_image_load_store_lod": loadVK_AMD_shader_image_load_store_lod, + "VK_AMD_display_native_hdr": loadVK_AMD_display_native_hdr, + "VK_NV_memory_decompression": loadVK_NV_memory_decompression, + "VK_EXT_direct_mode_display": loadVK_EXT_direct_mode_display, + "VK_EXT_fragment_shader_interlock": loadVK_EXT_fragment_shader_interlock, + "VK_NV_coverage_reduction_mode": loadVK_NV_coverage_reduction_mode, + "VK_KHR_get_display_properties2": loadVK_KHR_get_display_properties2, + "VK_INTEL_shader_integer_functions2": loadVK_INTEL_shader_integer_functions2, + "VK_NV_glsl_shader": loadVK_NV_glsl_shader, + "VK_KHR_shader_clock": loadVK_KHR_shader_clock, + "VK_EXT_image_2d_view_of_3d": loadVK_EXT_image_2d_view_of_3d, + "VK_QCOM_tile_properties": loadVK_QCOM_tile_properties, + "VK_KHR_push_descriptor": loadVK_KHR_push_descriptor, + "VK_NV_viewport_swizzle": loadVK_NV_viewport_swizzle, + "VK_KHR_ray_query": loadVK_KHR_ray_query, + "VK_KHR_present_wait": loadVK_KHR_present_wait, + "VK_NV_shading_rate_image": loadVK_NV_shading_rate_image, + "VK_EXT_fragment_density_map": loadVK_EXT_fragment_density_map, + "VK_NV_device_diagnostic_checkpoints": loadVK_NV_device_diagnostic_checkpoints, + "VK_EXT_pci_bus_info": loadVK_EXT_pci_bus_info, + "VK_NV_external_memory": loadVK_NV_external_memory, + "VK_EXT_queue_family_foreign": loadVK_EXT_queue_family_foreign, + "VK_KHR_swapchain_mutable_format": loadVK_KHR_swapchain_mutable_format, + "VK_EXT_depth_clip_control": loadVK_EXT_depth_clip_control, + "VK_EXT_debug_utils": loadVK_EXT_debug_utils, + "VK_KHR_portability_enumeration": loadVK_KHR_portability_enumeration, + "VK_EXT_memory_priority": loadVK_EXT_memory_priority, + "VK_EXT_validation_flags": loadVK_EXT_validation_flags, + "VK_AMD_shader_core_properties": loadVK_AMD_shader_core_properties, + "VK_EXT_conservative_rasterization": loadVK_EXT_conservative_rasterization, + "VK_KHR_external_fence_fd": loadVK_KHR_external_fence_fd, + "VK_NV_device_generated_commands": loadVK_NV_device_generated_commands, + "VK_NV_present_barrier": loadVK_NV_present_barrier, + "VK_AMD_gcn_shader": loadVK_AMD_gcn_shader, + "VK_NV_viewport_array2": loadVK_NV_viewport_array2, + "VK_INTEL_performance_query": loadVK_INTEL_performance_query, + "VK_NVX_multiview_per_view_attributes": loadVK_NVX_multiview_per_view_attributes, + "VK_EXT_primitives_generated_query": loadVK_EXT_primitives_generated_query, + "VK_AMD_pipeline_compiler_control": loadVK_AMD_pipeline_compiler_control, + "VK_EXT_post_depth_coverage": loadVK_EXT_post_depth_coverage, + "VK_EXT_rgba10x6_formats": loadVK_EXT_rgba10x6_formats, + "VK_KHR_external_memory_fd": loadVK_KHR_external_memory_fd, + "VK_NV_dedicated_allocation_image_aliasing": loadVK_NV_dedicated_allocation_image_aliasing, + "VK_NV_cooperative_matrix": loadVK_NV_cooperative_matrix, + "VK_EXT_depth_clamp_zero_one": loadVK_EXT_depth_clamp_zero_one, + "VK_EXT_conditional_rendering": loadVK_EXT_conditional_rendering, + "VK_QCOM_multiview_per_view_viewports": loadVK_QCOM_multiview_per_view_viewports, + "VK_NV_linear_color_attachment": loadVK_NV_linear_color_attachment, + "VK_EXT_shader_subgroup_ballot": loadVK_EXT_shader_subgroup_ballot, + "VK_EXT_multi_draw": loadVK_EXT_multi_draw, + "VK_NV_fragment_coverage_to_color": loadVK_NV_fragment_coverage_to_color, + "VK_EXT_load_store_op_none": loadVK_EXT_load_store_op_none, + "VK_QCOM_rotated_copy_commands": loadVK_QCOM_rotated_copy_commands, + "VK_EXT_surface_maintenance1": loadVK_EXT_surface_maintenance1, + "VK_EXT_swapchain_colorspace": loadVK_EXT_swapchain_colorspace, + "VK_EXT_image_drm_format_modifier": loadVK_EXT_image_drm_format_modifier, + "VK_EXT_validation_features": loadVK_EXT_validation_features, + "VK_KHR_workgroup_memory_explicit_layout": loadVK_KHR_workgroup_memory_explicit_layout, + "VK_EXT_index_type_uint8": loadVK_EXT_index_type_uint8, + "VK_EXT_mesh_shader": loadVK_EXT_mesh_shader, + "VK_AMD_shader_early_and_late_fragment_tests": loadVK_AMD_shader_early_and_late_fragment_tests, + "VK_KHR_display_swapchain": loadVK_KHR_display_swapchain, + "VK_EXT_transform_feedback": loadVK_EXT_transform_feedback, + "VK_GOOGLE_decorate_string": loadVK_GOOGLE_decorate_string, + "VK_EXT_shader_atomic_float": loadVK_EXT_shader_atomic_float, + "VK_EXT_acquire_drm_display": loadVK_EXT_acquire_drm_display, + "VK_EXT_pipeline_properties": loadVK_EXT_pipeline_properties, + "VK_EXT_graphics_pipeline_library": loadVK_EXT_graphics_pipeline_library, + "VK_KHR_acceleration_structure": loadVK_KHR_acceleration_structure, + "VK_AMD_shader_core_properties2": loadVK_AMD_shader_core_properties2, + "VK_KHR_surface": loadVK_KHR_surface, + "VK_AMD_gpu_shader_half_float": loadVK_AMD_gpu_shader_half_float, + "VK_KHR_deferred_host_operations": loadVK_KHR_deferred_host_operations, + "VK_NV_dedicated_allocation": loadVK_NV_dedicated_allocation, + "VK_GOOGLE_hlsl_functionality1": loadVK_GOOGLE_hlsl_functionality1, + "VK_EXT_robustness2": loadVK_EXT_robustness2, + "VK_NVX_image_view_handle": loadVK_NVX_image_view_handle, + "VK_EXT_non_seamless_cube_map": loadVK_EXT_non_seamless_cube_map, + "VK_EXT_opacity_micromap": loadVK_EXT_opacity_micromap, + "VK_EXT_image_view_min_lod": loadVK_EXT_image_view_min_lod, + "VK_AMD_shader_trinary_minmax": loadVK_AMD_shader_trinary_minmax, + "VK_QCOM_render_pass_store_ops": loadVK_QCOM_render_pass_store_ops, + "VK_EXT_device_fault": loadVK_EXT_device_fault, + "VK_EXT_custom_border_color": loadVK_EXT_custom_border_color, + "VK_EXT_mutable_descriptor_type": loadVK_EXT_mutable_descriptor_type, + "VK_AMD_rasterization_order": loadVK_AMD_rasterization_order, + "VK_EXT_vertex_input_dynamic_state": loadVK_EXT_vertex_input_dynamic_state, + "VK_KHR_incremental_present": loadVK_KHR_incremental_present, + "VK_KHR_fragment_shading_rate": loadVK_KHR_fragment_shading_rate, + "VK_EXT_color_write_enable": loadVK_EXT_color_write_enable, + "VK_SEC_amigo_profiling": loadVK_SEC_amigo_profiling, + "VK_GOOGLE_display_timing": loadVK_GOOGLE_display_timing, + "VK_NVX_binary_import": loadVK_NVX_binary_import, + "VK_EXT_depth_clip_enable": loadVK_EXT_depth_clip_enable, + "VK_EXT_subpass_merge_feedback": loadVK_EXT_subpass_merge_feedback, + "VK_NV_representative_fragment_test": loadVK_NV_representative_fragment_test, + "VK_EXT_validation_cache": loadVK_EXT_validation_cache, + "VK_EXT_display_control": loadVK_EXT_display_control, + "VK_KHR_external_semaphore_fd": loadVK_KHR_external_semaphore_fd, + "VK_KHR_fragment_shader_barycentric": loadVK_KHR_fragment_shader_barycentric, + "VK_NV_inherited_viewport_scissor": loadVK_NV_inherited_viewport_scissor, + "VK_EXT_legacy_dithering": loadVK_EXT_legacy_dithering, + "VK_NV_ray_tracing_motion_blur": loadVK_NV_ray_tracing_motion_blur, + "VK_EXT_physical_device_drm": loadVK_EXT_physical_device_drm, + "VK_EXT_pipeline_protected_access": loadVK_EXT_pipeline_protected_access, + "VK_QCOM_render_pass_transform": loadVK_QCOM_render_pass_transform, + "VK_GOOGLE_surfaceless_query": loadVK_GOOGLE_surfaceless_query, + "VK_EXT_memory_budget": loadVK_EXT_memory_budget, + "VK_EXT_discard_rectangles": loadVK_EXT_discard_rectangles, + "VK_EXT_shader_stencil_export": loadVK_EXT_shader_stencil_export, + "VK_KHR_shared_presentable_image": loadVK_KHR_shared_presentable_image, + "VK_NV_external_memory_rdma": loadVK_NV_external_memory_rdma, + "VK_EXT_image_compression_control_swapchain": loadVK_EXT_image_compression_control_swapchain, + "VK_EXT_hdr_metadata": loadVK_EXT_hdr_metadata, + "VK_AMD_device_coherent_memory": loadVK_AMD_device_coherent_memory, + "VK_EXT_device_memory_report": loadVK_EXT_device_memory_report, + "VK_ARM_shader_core_builtins": loadVK_ARM_shader_core_builtins, + "VK_QCOM_multiview_per_view_render_areas": loadVK_QCOM_multiview_per_view_render_areas, + "VK_LUNARG_direct_driver_loading": loadVK_LUNARG_direct_driver_loading, + "VK_AMD_memory_overallocation_behavior": loadVK_AMD_memory_overallocation_behavior, + "VK_NV_mesh_shader": loadVK_NV_mesh_shader, + "VK_AMD_shader_explicit_vertex_parameter": loadVK_AMD_shader_explicit_vertex_parameter, + "VK_EXT_headless_surface": loadVK_EXT_headless_surface, + "VK_NV_shader_sm_builtins": loadVK_NV_shader_sm_builtins, + "VK_EXT_shader_subgroup_vote": loadVK_EXT_shader_subgroup_vote, + "VK_NV_copy_memory_indirect": loadVK_NV_copy_memory_indirect, + "VK_EXT_image_compression_control": loadVK_EXT_image_compression_control, + "VK_EXT_astc_decode_mode": loadVK_EXT_astc_decode_mode, + "VK_EXT_buffer_device_address": loadVK_EXT_buffer_device_address, + "VK_KHR_get_surface_capabilities2": loadVK_KHR_get_surface_capabilities2, + "VK_KHR_display": loadVK_KHR_display, + "VK_QCOM_render_pass_shader_resolve": loadVK_QCOM_render_pass_shader_resolve, + "VK_EXT_depth_range_unrestricted": loadVK_EXT_depth_range_unrestricted, + "VK_HUAWEI_subpass_shading": loadVK_HUAWEI_subpass_shading, + "VK_VALVE_descriptor_set_host_mapping": loadVK_VALVE_descriptor_set_host_mapping, + "VK_HUAWEI_cluster_culling_shader": loadVK_HUAWEI_cluster_culling_shader, + "VK_KHR_surface_protected_capabilities": loadVK_KHR_surface_protected_capabilities, + "VK_NV_shader_image_footprint": loadVK_NV_shader_image_footprint, + "VK_NV_external_memory_capabilities": loadVK_NV_external_memory_capabilities, + "VK_NV_compute_shader_derivatives": loadVK_NV_compute_shader_derivatives, + "VK_QCOM_fragment_density_map_offset": loadVK_QCOM_fragment_density_map_offset, +}.toTable +when defined(VK_USE_PLATFORM_XLIB_KHR): + include ../vulkan/platform/xlib + EXTENSION_LOADERS["VK_KHR_xlib_surface"] = loadVK_KHR_xlib_surface +when defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT): + include ../vulkan/platform/xlib_xrandr + EXTENSION_LOADERS["VK_EXT_acquire_xlib_display"] = loadVK_EXT_acquire_xlib_display +when defined(VK_USE_PLATFORM_XCB_KHR): + include ../vulkan/platform/xcb + EXTENSION_LOADERS["VK_KHR_xcb_surface"] = loadVK_KHR_xcb_surface +when defined(VK_USE_PLATFORM_WAYLAND_KHR): + include ../vulkan/platform/wayland + EXTENSION_LOADERS["VK_KHR_wayland_surface"] = loadVK_KHR_wayland_surface +when defined(VK_USE_PLATFORM_DIRECTFB_EXT): + include ../vulkan/platform/directfb + EXTENSION_LOADERS["VK_EXT_directfb_surface"] = loadVK_EXT_directfb_surface +when defined(VK_USE_PLATFORM_ANDROID_KHR): + include ../vulkan/platform/android + EXTENSION_LOADERS["VK_KHR_android_surface"] = loadVK_KHR_android_surface + EXTENSION_LOADERS["VK_ANDROID_external_memory_android_hardware_buffer"] = loadVK_ANDROID_external_memory_android_hardware_buffer +when defined(VK_USE_PLATFORM_WIN32_KHR): + include ../vulkan/platform/win32 + EXTENSION_LOADERS["VK_KHR_external_semaphore_win32"] = loadVK_KHR_external_semaphore_win32 + EXTENSION_LOADERS["VK_EXT_full_screen_exclusive"] = loadVK_EXT_full_screen_exclusive + EXTENSION_LOADERS["VK_NV_external_memory_win32"] = loadVK_NV_external_memory_win32 + EXTENSION_LOADERS["VK_KHR_external_memory_win32"] = loadVK_KHR_external_memory_win32 + EXTENSION_LOADERS["VK_NV_acquire_winrt_display"] = loadVK_NV_acquire_winrt_display + EXTENSION_LOADERS["VK_KHR_win32_surface"] = loadVK_KHR_win32_surface + EXTENSION_LOADERS["VK_KHR_external_fence_win32"] = loadVK_KHR_external_fence_win32 + EXTENSION_LOADERS["VK_KHR_win32_keyed_mutex"] = loadVK_KHR_win32_keyed_mutex +when defined(VK_USE_PLATFORM_VI_NN): + include ../vulkan/platform/vi + EXTENSION_LOADERS["VK_NN_vi_surface"] = loadVK_NN_vi_surface +when defined(VK_USE_PLATFORM_IOS_MVK): + include ../vulkan/platform/ios + EXTENSION_LOADERS["VK_MVK_ios_surface"] = loadVK_MVK_ios_surface +when defined(VK_USE_PLATFORM_MACOS_MVK): + include ../vulkan/platform/macos + EXTENSION_LOADERS["VK_MVK_macos_surface"] = loadVK_MVK_macos_surface +when defined(VK_USE_PLATFORM_METAL_EXT): + include ../vulkan/platform/metal + EXTENSION_LOADERS["VK_EXT_metal_objects"] = loadVK_EXT_metal_objects + EXTENSION_LOADERS["VK_EXT_metal_surface"] = loadVK_EXT_metal_surface +when defined(VK_USE_PLATFORM_FUCHSIA): + include ../vulkan/platform/fuchsia + EXTENSION_LOADERS["VK_FUCHSIA_external_semaphore"] = loadVK_FUCHSIA_external_semaphore + EXTENSION_LOADERS["VK_FUCHSIA_imagepipe_surface"] = loadVK_FUCHSIA_imagepipe_surface + EXTENSION_LOADERS["VK_FUCHSIA_external_memory"] = loadVK_FUCHSIA_external_memory + EXTENSION_LOADERS["VK_FUCHSIA_buffer_collection"] = loadVK_FUCHSIA_buffer_collection +when defined(VK_USE_PLATFORM_GGP): + include ../vulkan/platform/ggp + EXTENSION_LOADERS["VK_GGP_frame_token"] = loadVK_GGP_frame_token + EXTENSION_LOADERS["VK_GGP_stream_descriptor_surface"] = loadVK_GGP_stream_descriptor_surface +when defined(VK_USE_PLATFORM_SCI): + include ../vulkan/platform/sci +when defined(VK_ENABLE_BETA_EXTENSIONS): + include ../vulkan/platform/provisional + EXTENSION_LOADERS["VK_KHR_video_encode_queue"] = loadVK_KHR_video_encode_queue + EXTENSION_LOADERS["VK_KHR_video_queue"] = loadVK_KHR_video_queue + EXTENSION_LOADERS["VK_EXT_video_encode_h264"] = loadVK_EXT_video_encode_h264 + EXTENSION_LOADERS["VK_EXT_video_encode_h265"] = loadVK_EXT_video_encode_h265 + EXTENSION_LOADERS["VK_KHR_video_decode_queue"] = loadVK_KHR_video_decode_queue + EXTENSION_LOADERS["VK_KHR_video_decode_h264"] = loadVK_KHR_video_decode_h264 + EXTENSION_LOADERS["VK_KHR_portability_subset"] = loadVK_KHR_portability_subset + EXTENSION_LOADERS["VK_KHR_video_decode_h265"] = loadVK_KHR_video_decode_h265 +when defined(VK_USE_PLATFORM_SCREEN_QNX): + include ../vulkan/platform/screen + EXTENSION_LOADERS["VK_QNX_screen_surface"] = loadVK_QNX_screen_surface + +proc loadExtension*(instance: VkInstance, extension: string) = + if extension in EXTENSION_LOADERS: + EXTENSION_LOADERS[extension](instance) + +# load global functions immediately +block globalFunctions: + let instance = VkInstance(0) + vkEnumerateInstanceVersion = cast[proc(pApiVersion: ptr uint32): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumerateInstanceVersion")) + vkEnumerateInstanceExtensionProperties = cast[proc(pLayerName: cstring, pPropertyCount: ptr uint32, pProperties: ptr VkExtensionProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumerateInstanceExtensionProperties")) + vkEnumerateInstanceLayerProperties = cast[proc(pPropertyCount: ptr uint32, pProperties: ptr VkLayerProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumerateInstanceLayerProperties")) + vkCreateInstance = cast[proc(pCreateInfo: ptr VkInstanceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pInstance: ptr VkInstance): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateInstance")) + +converter NimBool2VkBool*(a: bool): VkBool32 = VkBool32(a) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/engine.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/engine.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,210 @@ +import std/options +import std/logging +import std/os + +import ./platform/window + +import ./core +import ./vulkan/instance +import ./vulkan/device +import ./vulkan/physicaldevice +import ./vulkan/shader + +import ./scene +import ./material +import ./renderer +import ./events +import ./audio +import ./text + +type + EngineState* = enum + Starting + Running + Shutdown + Input = object + keyIsDown: set[Key] + keyWasPressed: set[Key] + keyWasReleased: set[Key] + mouseIsDown: set[MouseButton] + mouseWasPressed: set[MouseButton] + mouseWasReleased: set[MouseButton] + mousePosition: Vec2f + mouseMove: Vec2f + eventsProcessed: uint64 + windowWasResized: bool + mouseWheel: float32 + Engine* = object + state*: EngineState + device: Device + debugger: Debugger + instance: Instance + window: NativeWindow + renderer: Option[Renderer] + input: Input + exitHandler: proc(engine: var Engine) + resizeHandler: proc(engine: var Engine) + eventHandler: proc(engine: var Engine, event: Event) + + +proc destroy*(engine: var Engine) = + checkVkResult engine.device.vk.vkDeviceWaitIdle() + if engine.renderer.isSome: + engine.renderer.get.destroy() + engine.device.destroy() + if engine.debugger.messenger.valid: + engine.debugger.destroy() + engine.window.destroy() + engine.instance.destroy() + + +proc initEngine*( + applicationName: string, + debug=DEBUG, + exitHandler: proc(engine: var Engine) = nil, + resizeHandler: proc(engine: var Engine) = nil, + eventHandler: proc(engine: var Engine, event: Event) = nil +): Engine = + echo "Set log level to ", ENGINE_LOGLEVEL + setLogFilter(ENGINE_LOGLEVEL) + + result.state = Starting + result.exitHandler = exitHandler + result.resizeHandler = resizeHandler + result.eventHandler = eventHandler + result.window = createWindow(applicationName) + + var + instanceExtensions: seq[string] + enabledLayers: seq[string] + + if debug: + instanceExtensions.add "VK_EXT_debug_utils" + enabledLayers.add "VK_LAYER_KHRONOS_validation" + # putEnv("VK_LAYER_ENABLES", "VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT") + putEnv("VK_LAYER_ENABLES", "") + + if defined(linux) and DEBUG: + enabledLayers.add "VK_LAYER_MESA_overlay" + result.instance = result.window.createInstance( + vulkanVersion=VK_MAKE_API_VERSION(0, 1, 3, 0), + instanceExtensions=instanceExtensions, + layers=enabledLayers, + ) + if debug: + result.debugger = result.instance.createDebugMessenger() + # create devices + let selectedPhysicalDevice = result.instance.getPhysicalDevices().filterBestGraphics() + result.device = result.instance.createDevice( + selectedPhysicalDevice, + enabledLayers = @[], + enabledExtensions = @[], + selectedPhysicalDevice.filterForGraphicsPresentationQueues() + ) + startMixerThread() + +proc initRenderer*(engine: var Engine, shaders: openArray[(MaterialType, ShaderConfiguration)], clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32]), backFaceCulling=true) = + + assert not engine.renderer.isSome + var allShaders = @shaders + allShaders.add (TEXT_MATERIAL_TYPE, TEXT_SHADER) + engine.renderer = some(engine.device.initRenderer(shaders=allShaders, clearColor=clearColor, backFaceCulling=backFaceCulling)) + +proc initRenderer*(engine: var Engine, clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32])) = + engine.initRenderer(@[], clearColor) + +proc loadScene*(engine: var Engine, scene: var Scene) = + assert engine.renderer.isSome + assert not scene.loaded + engine.renderer.get.setupDrawableBuffers(scene) + engine.renderer.get.updateMeshData(scene, forceAll=true) + engine.renderer.get.updateUniformData(scene, forceAll=true) + +proc unloadScene*(engine: var Engine, scene: Scene) = + engine.renderer.get.destroy(scene) + +proc renderScene*(engine: var Engine, scene: var Scene) = + assert engine.state == Running + assert engine.renderer.isSome + engine.renderer.get.updateMeshData(scene) + engine.renderer.get.updateUniformData(scene) + engine.renderer.get.render(scene) + +proc updateInputs*(engine: var Engine): EngineState = + assert engine.state in [Starting, Running] + + # reset input states + engine.input.keyWasPressed = {} + engine.input.keyWasReleased = {} + engine.input.mouseWasPressed = {} + engine.input.mouseWasReleased = {} + engine.input.mouseWheel = 0 + engine.input.mouseMove = newVec2f() + engine.input.windowWasResized = false + + if engine.state == Starting: + engine.input.windowWasResized = true + var mpos = engine.window.getMousePosition() + if mpos.isSome: + engine.input.mousePosition = mpos.get + + var killed = false + for event in engine.window.pendingEvents(): + inc engine.input.eventsProcessed + if engine.eventHandler != nil: + engine.eventHandler(engine, event) + case event.eventType: + of Quit: + killed = true + of ResizedWindow: + engine.input.windowWasResized = true + of KeyPressed: + engine.input.keyWasPressed.incl event.key + engine.input.keyIsDown.incl event.key + of KeyReleased: + engine.input.keyWasReleased.incl event.key + engine.input.keyIsDown.excl event.key + of MousePressed: + engine.input.mouseWasPressed.incl event.button + engine.input.mouseIsDown.incl event.button + of MouseReleased: + engine.input.mouseWasReleased.incl event.button + engine.input.mouseIsDown.excl event.button + of MouseMoved: + let newPos = newVec2(float32(event.x), float32(event.y)) + engine.input.mouseMove = newPos - engine.input.mousePosition + engine.input.mousePosition = newPos + of MouseWheel: + engine.input.mouseWheel = event.amount + if engine.state == Starting: + engine.state = Running + if killed: + engine.state = Shutdown + if engine.exitHandler != nil: + engine.exitHandler(engine) + if engine.input.windowWasResized and engine.resizeHandler != nil: + engine.resizeHandler(engine) + return engine.state + +# wrappers for internal things +func keyIsDown*(engine: Engine, key: Key): auto = key in engine.input.keyIsDown +func keyWasPressed*(engine: Engine, key: Key): auto = key in engine.input.keyWasPressed +func keyWasPressed*(engine: Engine): auto = engine.input.keyWasPressed.len > 0 +func keyWasReleased*(engine: Engine, key: Key): auto = key in engine.input.keyWasReleased +func mouseIsDown*(engine: Engine, button: MouseButton): auto = button in engine.input.mouseIsDown +func mouseWasPressed*(engine: Engine, button: MouseButton): auto = button in engine.input.mouseWasPressed +func mouseWasReleased*(engine: Engine, button: MouseButton): auto = button in engine.input.mouseWasReleased +func mousePosition*(engine: Engine): auto = engine.input.mousePosition +func mousePositionNormalized*(engine: Engine): Vec2f = + result.x = (engine.input.mousePosition.x / float32(engine.window.size[0])) * 2.0 - 1.0 + result.y = (engine.input.mousePosition.y / float32(engine.window.size[1])) * 2.0 - 1.0 +func mouseMove*(engine: Engine): auto = engine.input.mouseMove +func mouseWheel*(engine: Engine): auto = engine.input.mouseWheel +func eventsProcessed*(engine: Engine): auto = engine.input.eventsProcessed +func framesRendered*(engine: Engine): uint64 = (if engine.renderer.isSome: engine.renderer.get.framesRendered else: 0) +func gpuDevice*(engine: Engine): Device = engine.device +func getWindow*(engine: Engine): auto = engine.window +func windowWasResized*(engine: Engine): auto = engine.input.windowWasResized +func showSystemCursor*(engine: Engine) = engine.window.showSystemCursor() +func hideSystemCursor*(engine: Engine) = engine.window.hideSystemCursor() +proc fullscreen*(engine: var Engine, enable: bool) = engine.window.fullscreen(enable) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/events.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/events.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,35 @@ +type + EventType* = enum + Quit + ResizedWindow + KeyPressed, KeyReleased + MousePressed, MouseReleased, MouseMoved, + MouseWheel + Key* {.size: sizeof(cint), pure.} = enum + UNKNOWN + Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12 + NumberRowExtra1, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `0`, + NumberRowExtra2, NumberRowExtra3 # tilde, minus, plus + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z + Tab, CapsLock, ShiftL, ShiftR, CtrlL, CtrlR, SuperL, SuperR, AltL, AltR, + Space, Enter, Backspace + LetterRow1Extra1, LetterRow1Extra2 # open bracket, close brackt, backslash + LetterRow2Extra1, LetterRow2Extra2, LetterRow2Extra3 # semicolon, quote + LetterRow3Extra1, LetterRow3Extra2, LetterRow3Extra3 # comma, period, slash + Up, Down, Left, Right + PageUp, PageDown, Home, End, Insert, Delete + PrintScreen, ScrollLock, Pause + MouseButton* {.size: sizeof(cint), pure.} = enum + UNKNOWN, Mouse1, Mouse2, Mouse3 + Event* = object + case eventType*: EventType + of KeyPressed, KeyReleased: + key*: Key + of MousePressed, MouseReleased: + button*: MouseButton + of MouseMoved: + x*, y*: int + of MouseWheel: + amount*: float32 + else: + discard diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/material.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/material.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,110 @@ +import std/tables +import std/strformat +import std/strutils +import std/hashes + + +import ./core + +type + MaterialType* = object + name*: string + vertexAttributes*: Table[string, DataType] + instanceAttributes*: Table[string, DataType] + attributes*: Table[string, DataType] + MaterialData* = object + theType*: MaterialType + name*: string + attributes*: Table[string, DataList] + +proc hash*(materialType: MaterialType): Hash = + return hash(materialType.name) + +proc hash*(materialData: MaterialData): Hash = + return hash(materialData.name) + +proc `==`*(a, b: MaterialType): bool = + return a.name == b.name + +proc `==`*(a, b: MaterialData): bool = + return a.name == b.name + +let EMPTY_MATERIAL* = MaterialType( + name: "empty material", + vertexAttributes: {"position": Vec3F32}.toTable, +) +let COLORED_MATERIAL* = MaterialType( + name: "single color material", + vertexAttributes: {"position": Vec3F32}.toTable, + attributes: {"color": Vec4F32}.toTable, +) +let VERTEX_COLORED_MATERIAL* = MaterialType( + name: "vertex color material", + vertexAttributes: { + "position": Vec3F32, + "color": Vec4F32, + }.toTable, +) +let SINGLE_COLOR_MATERIAL* = MaterialType( + name: "single color material", + vertexAttributes: { + "position": Vec3F32, + }.toTable, + attributes: {"color": Vec4F32}.toTable +) +let SINGLE_TEXTURE_MATERIAL* = MaterialType( + name: "single texture material", + vertexAttributes: { + "position": Vec3F32, + "uv": Vec2F32, + }.toTable, + attributes: {"baseTexture": TextureType}.toTable +) +let COLORED_SINGLE_TEXTURE_MATERIAL* = MaterialType( + name: "colored single texture material", + vertexAttributes: { + "position": Vec3F32, + "uv": Vec2F32, + }.toTable, + attributes: {"baseTexture": TextureType, "color": Vec4F32}.toTable +) + +proc `$`*(materialType: MaterialType): string = + var attributes: seq[string] + for key, value in materialType.attributes.pairs: + attributes.add &"{key}: {value}" + return &"""MaterialType '{materialType.name}' | Attributes: {attributes.join(", ")}""" + +proc `$`*(material: MaterialData): string = + var attributes: seq[string] + for key, value in material.attributes.pairs: + attributes.add &"{key}: {value}" + return &"""Material '{material.name}' | Attributes: {attributes.join(", ")}""" + +proc initMaterialData*( + materialType: MaterialType, + name: string, + attributes: Table[string, DataList], +): MaterialData = + var theName = name + if theName == "": + theName = &"material instance of '{materialType}'" + for matName, theType in materialType.attributes.pairs: + assert attributes.contains(matName), &"missing material attribute '{matName}' for {materialType}" + assert attributes[matName].theType == theType + MaterialData( + theType: materialType, + name: theName, + attributes: attributes, + ) + +proc initMaterialData*( + materialType: MaterialType, + name: string = "", + attributes: openArray[(string, DataList)] = @[], +): MaterialData = + var theName = name + if theName == "": + theName = &"material instance of '{materialType}'" + initMaterialData(materialType=materialType, name=theName, attributes=attributes.toTable) + diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/mesh.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/mesh.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,538 @@ +import std/hashes +import std/options +import std/typetraits +import std/tables +import std/strformat +import std/enumerate +import std/strutils +import std/sequtils + +import ./core +import ./collision +import ./material + +const DEFAULT_POSITION_ATTRIBUTE = "position" + +var instanceCounter* = 0 + +type + MeshIndexType* = enum + None + Tiny # up to 2^8 vertices # TODO: need to check and enable support for this + Small # up to 2^16 vertices + Big # up to 2^32 vertices + MeshObject* = object + name*: string + vertexCount*: int + case indexType*: MeshIndexType + of None: discard + of Tiny: tinyIndices*: seq[array[3, uint8]] + of Small: smallIndices*: seq[array[3, uint16]] + of Big: bigIndices*: seq[array[3, uint32]] + material*: MaterialData + transform*: Mat4 = Unit4 + instanceTransforms*: seq[Mat4] + applyMeshTransformToInstances*: bool = true # if true, the transform attribute for the shader will apply the instance transform AND the mesh transform, to each instance + visible*: bool = true + transformCache: seq[Mat4] + vertexData: Table[string, DataList] + instanceData: Table[string, DataList] + dirtyAttributes: seq[string] + Mesh* = ref MeshObject + +func material*(mesh: MeshObject): MaterialData = + mesh.material + +func `material=`*(mesh: var MeshObject, material: MaterialData) = + for name, theType in material.theType.vertexAttributes: + if mesh.vertexData.contains(name): + assert mesh.vertexData[name].theType == theType, &"{material.theType} expected mesh attribute '{name}' to be '{theType}' but it is {mesh.vertexData[name].theType}" + elif mesh.instanceData.contains(name): + assert mesh.instanceData[name].theType == theType, &"{material.theType} expected mesh attribute '{name}' to be '{theType}' but it is {mesh.instanceData[name].theType}" + else: + assert false, &"Mesh '{mesh.name}' is missing required mesh attribute '{name}: {theType}' for {material.theType}" + mesh.material = material + +func instanceCount*(mesh: MeshObject): int = + mesh.instanceTransforms.len + +func indicesCount*(mesh: MeshObject): int = + ( + case mesh.indexType + of None: 0 + of Tiny: mesh.tinyIndices.len + of Small: mesh.smallIndices.len + of Big: mesh.bigIndices.len + ) * 3 + +func `$`*(mesh: MeshObject): string = + if mesh.indexType == None: + &"Mesh('{mesh.name}', vertexCount: {mesh.vertexCount}, instanceCount: {mesh.instanceCount}, vertexData: {mesh.vertexData.keys().toSeq()}, instanceData: {mesh.instanceData.keys().toSeq()}, indexType: {mesh.indexType}, material: {mesh.material})" + else: + &"Mesh('{mesh.name}', vertexCount: {mesh.vertexCount}, indexCount: {mesh.indicesCount}, instanceCount: {mesh.instanceCount}, vertexData: {mesh.vertexData.keys().toSeq()}, instanceData: {mesh.instanceData.keys().toSeq()}, indexType: {mesh.indexType}, material: {mesh.material})" +func `$`*(mesh: Mesh): string = + $mesh[] + +func vertexAttributes*(mesh: MeshObject): seq[string] = + mesh.vertexData.keys.toSeq + +func instanceAttributes*(mesh: MeshObject): seq[string] = + mesh.instanceData.keys.toSeq + +func attributes*(mesh: MeshObject): seq[string] = + mesh.vertexAttributes & mesh.instanceAttributes + +func hash*(mesh: Mesh): Hash = + hash(cast[ptr MeshObject](mesh)) + +converter toVulkan*(indexType: MeshIndexType): VkIndexType = + case indexType: + of None: VK_INDEX_TYPE_NONE_KHR + of Tiny: VK_INDEX_TYPE_UINT8_EXT + of Small: VK_INDEX_TYPE_UINT16 + of Big: VK_INDEX_TYPE_UINT32 + +proc initVertexAttribute*[T](mesh: var MeshObject, attribute: string, value: seq[T]) = + assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) + mesh.vertexData[attribute] = initDataList(thetype=getDataType[T]()) + mesh.vertexData[attribute].setLen(mesh.vertexCount) + mesh.vertexData[attribute].setValues(value) +proc initVertexAttribute*[T](mesh: var MeshObject, attribute: string, value: T) = + initVertexAttribute(mesh, attribute, newSeqWith(mesh.vertexCount, value)) +proc initVertexAttribute*[T](mesh: var MeshObject, attribute: string) = + initVertexAttribute(mesh=mesh, attribute=attribute, value=default(T)) +proc initVertexAttribute*(mesh: var MeshObject, attribute: string, datatype: DataType) = + assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) + mesh.vertexData[attribute] = initDataList(thetype=datatype) + mesh.vertexData[attribute].setLen(mesh.vertexCount) +proc initVertexAttribute*(mesh: var MeshObject, attribute: string, data: DataList) = + assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) + mesh.vertexData[attribute] = data + + +proc initInstanceAttribute*[T](mesh: var MeshObject, attribute: string, value: seq[T]) = + assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) + mesh.instanceData[attribute] = initDataList(thetype=getDataType[T]()) + mesh.instanceData[attribute].setLen(mesh.instanceCount) + mesh.instanceData[attribute].setValues(value) +proc initInstanceAttribute*[T](mesh: var MeshObject, attribute: string, value: T) = + initInstanceAttribute(mesh, attribute, newSeqWith(mesh.instanceCount, value)) +proc initInstanceAttribute*[T](mesh: var MeshObject, attribute: string) = + initInstanceAttribute(mesh=mesh, attribute=attribute, value=default(T)) +proc initInstanceAttribute*(mesh: var MeshObject, attribute: string, datatype: DataType) = + assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) + mesh.instanceData[attribute] = initDataList(thetype=datatype) + mesh.instanceData[attribute].setLen(mesh.instanceCount) +proc initInstanceAttribute*(mesh: var MeshObject, attribute: string, data: DataList) = + assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) + mesh.instanceData[attribute] = data + +proc newMesh*( + positions: openArray[Vec3f], + indices: openArray[array[3, uint32|uint16|uint8]], + colors: openArray[Vec4f]=[], + uvs: openArray[Vec2f]=[], + transform: Mat4=Unit4F32, + instanceTransforms: openArray[Mat4]=[Unit4F32], + material=EMPTY_MATERIAL.initMaterialData(), + autoResize=true, + name: string="" +): Mesh = + assert colors.len == 0 or colors.len == positions.len + assert uvs.len == 0 or uvs.len == positions.len + var theName = name + if theName == "": + theName = &"mesh-{instanceCounter}" + inc instanceCounter + + # determine index type (uint8, uint16, uint32) + var indexType = None + if indices.len > 0: + indexType = Big + if autoResize and uint32(positions.len) < uint32(high(uint8)) and false: # TODO: check feature support + indexType = Tiny + elif autoResize and uint32(positions.len) < uint32(high(uint16)): + indexType = Small + + result = Mesh( + name: theName, + indexType: indexType, + vertexCount: positions.len, + instanceTransforms: @instanceTransforms, + transform: transform, + material: material + ) + + result[].initVertexAttribute(DEFAULT_POSITION_ATTRIBUTE , positions.toSeq) + if colors.len > 0: result[].initVertexAttribute("color", colors.toSeq) + if uvs.len > 0: result[].initVertexAttribute("uv", uvs.toSeq) + + # assert all indices are valid + for i in indices: + assert int(i[0]) < result[].vertexCount + assert int(i[1]) < result[].vertexCount + assert int(i[2]) < result[].vertexCount + + # cast index values to appropiate type + if result[].indexType == Tiny and uint32(positions.len) < uint32(high(uint8)) and false: # TODO: check feature support + for i, tri in enumerate(indices): + result[].tinyIndices.add [uint8(tri[0]), uint8(tri[1]), uint8(tri[2])] + elif result[].indexType == Small and uint32(positions.len) < uint32(high(uint16)): + for i, tri in enumerate(indices): + result[].smallIndices.add [uint16(tri[0]), uint16(tri[1]), uint16(tri[2])] + elif result[].indexType == Big: + for i, tri in enumerate(indices): + result[].bigIndices.add [uint32(tri[0]), uint32(tri[1]), uint32(tri[2])] + +proc newMesh*( + positions: openArray[Vec3f], + colors: openArray[Vec4f]=[], + uvs: openArray[Vec2f]=[], + transform: Mat4=Unit4F32, + instanceTransforms: openArray[Mat4]=[Unit4F32], + material=EMPTY_MATERIAL.initMaterialData(), + name: string="", +): Mesh = + newMesh( + positions=positions, + indices=newSeq[array[3, uint16]](), + colors=colors, + uvs=uvs, + transform=transform, + instanceTransforms=instanceTransforms, + material=material, + name=name, + ) + +func attributeSize*(mesh: MeshObject, attribute: string): int = + if mesh.vertexData.contains(attribute): + mesh.vertexData[attribute].size + elif mesh.instanceData.contains(attribute): + mesh.instanceData[attribute].size + else: + 0 + +func attributeType*(mesh: MeshObject, attribute: string): DataType = + if mesh.vertexData.contains(attribute): + mesh.vertexData[attribute].theType + elif mesh.instanceData.contains(attribute): + mesh.instanceData[attribute].theType + else: + raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") + +func indexSize*(mesh: MeshObject): int = + case mesh.indexType + of None: 0 + of Tiny: mesh.tinyIndices.len * sizeof(get(genericParams(typeof(mesh.tinyIndices)), 0)) + of Small: mesh.smallIndices.len * sizeof(get(genericParams(typeof(mesh.smallIndices)), 0)) + of Big: mesh.bigIndices.len * sizeof(get(genericParams(typeof(mesh.bigIndices)), 0)) + +func rawData[T: seq](value: T): (pointer, int) = + (pointer(addr(value[0])), sizeof(get(genericParams(typeof(value)), 0)) * value.len) + +func getRawIndexData*(mesh: MeshObject): (pointer, int) = + case mesh.indexType: + of None: raise newException(Exception, "Trying to get index data for non-indexed mesh") + of Tiny: rawData(mesh.tinyIndices) + of Small: rawData(mesh.smallIndices) + of Big: rawData(mesh.bigIndices) + +func getRawData*(mesh: var MeshObject, attribute: string): (pointer, int) = + if mesh.vertexData.contains(attribute): + mesh.vertexData[attribute].getRawData() + elif mesh.instanceData.contains(attribute): + mesh.instanceData[attribute].getRawData() + else: + raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") + +proc getAttribute[T: GPUType|int|uint|float](mesh: MeshObject, attribute: string): ref seq[T] = + if mesh.vertexData.contains(attribute): + getValues[T](mesh.vertexData[attribute]) + elif mesh.instanceData.contains(attribute): + getValues[T](mesh.instanceData[attribute]) + else: + raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") + +proc getAttribute[T: GPUType|int|uint|float](mesh: MeshObject, attribute: string, i: int): T = + if mesh.vertexData.contains(attribute): + getValue[T](mesh.vertexData[attribute], i) + elif mesh.instanceData.contains(attribute): + getValue[T](mesh.instanceData[attribute], i) + else: + raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") + +template `[]`*(mesh: MeshObject, attribute: string, t: typedesc): ref seq[t] = + getAttribute[t](mesh, attribute) +template `[]`*(mesh: Mesh, attribute: string, t: typedesc): ref seq[t] = + getAttribute[t](mesh[], attribute) +template `[]`*(mesh: MeshObject, attribute: string, i: int, t: typedesc): untyped = + getAttribute[t](mesh, attribute, i) +template `[]`*(mesh: Mesh, attribute: string, i: int, t: typedesc): untyped = + getAttribute[t](mesh[], attribute, i) + +proc updateAttributeData[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, data: DataList) = + if mesh.vertexData.contains(attribute): + assert data.len == mesh.vertexCount + assert data.theType == mesh.vertexData[attribute].theType + mesh.vertexData[attribute] = data + elif mesh.instanceData.contains(attribute): + assert data.len == mesh.instanceCount + assert data.theType == mesh.instanceData[attribute].theType + mesh.instanceData[attribute] = data + else: + raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") + if not mesh.dirtyAttributes.contains(attribute): + mesh.dirtyAttributes.add attribute + +proc updateAttributeData[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, data: seq[T]) = + if mesh.vertexData.contains(attribute): + assert data.len == mesh.vertexCount + setValues(mesh.vertexData[attribute], data) + elif mesh.instanceData.contains(attribute): + assert data.len == mesh.instanceCount + setValues(mesh.instanceData[attribute], data) + else: + raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") + if not mesh.dirtyAttributes.contains(attribute): + mesh.dirtyAttributes.add attribute + +proc updateAttributeData[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, i: int, value: T) = + if mesh.vertexData.contains(attribute): + assert i < mesh.vertexData[attribute].len + setValue(mesh.vertexData[attribute], i, value) + elif mesh.instanceData.contains(attribute): + assert i < mesh.instanceData[attribute].len + setValue(mesh.instanceData[attribute], i, value) + else: + raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") + if not mesh.dirtyAttributes.contains(attribute): + mesh.dirtyAttributes.add attribute + +proc `[]=`*[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, data: DataList) = + updateAttributeData[T](mesh, attribute, data) +proc `[]=`*[T: GPUType|int|uint|float](mesh: Mesh, attribute: string, data: DataList) = + updateAttributeData[t](mesh[], attribute, data) + +proc `[]=`*[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, data: seq[T]) = + updateAttributeData[T](mesh, attribute, data) +proc `[]=`*[T: GPUType|int|uint|float](mesh: Mesh, attribute: string, data: seq[T]) = + updateAttributeData[t](mesh[], attribute, data) + +proc `[]=`*[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, value: T) = + updateAttributeData[T](mesh, attribute, newSeqWith(mesh.vertexCount, value)) +proc `[]=`*[T: GPUType|int|uint|float](mesh: Mesh, attribute: string, value: T) = + updateAttributeData[T](mesh[], attribute, newSeqWith(mesh.vertexCount, value)) + +proc `[]=`*[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, i: int, value: T) = + updateAttributeData[T](mesh, attribute, i, value) +proc `[]=`*[T: GPUType|int|uint|float](mesh: Mesh, attribute: string, i: int, value: T) = + updateAttributeData[T](mesh[], attribute, i, value) + +proc removeAttribute*(mesh: var MeshObject, attribute: string) = + if mesh.vertexData.contains(attribute): + mesh.vertexData.del(attribute) + elif mesh.instanceData.contains(attribute): + mesh.instanceData.del(attribute) + else: + raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") + +proc appendIndicesData*(mesh: var MeshObject, v1, v2, v3: int) = + case mesh.indexType + of None: raise newException(Exception, "Mesh does not support indexed data") + of Tiny: mesh.tinyIndices.add([uint8(v1), uint8(v2), uint8(v3)]) + of Small: mesh.smallIndices.add([uint16(v1), uint16(v2), uint16(v3)]) + of Big: mesh.bigIndices.add([uint32(v1), uint32(v2), uint32(v3)]) + +proc updateInstanceTransforms*(mesh: var MeshObject, attribute: string) = + var currentTransforms: seq[Mat4] + if mesh.applyMeshTransformToInstances: + currentTransforms = mesh.instanceTransforms.mapIt(mesh.transform * it) + else: + currentTransforms = mesh.instanceTransforms + if currentTransforms != mesh.transformCache: + mesh[attribute] = currentTransforms + mesh.transformCache = currentTransforms + +proc renameAttribute*(mesh: var MeshObject, oldname, newname: string) = + if mesh.vertexData.contains(oldname): + mesh.vertexData[newname] = mesh.vertexData[oldname] + mesh.vertexData.del oldname + elif mesh.instanceData.contains(oldname): + mesh.instanceData[newname] = mesh.vertexData[oldname] + mesh.instanceData.del oldname + else: + raise newException(Exception, &"Attribute {oldname} is not defined for mesh {mesh}") + +func dirtyAttributes*(mesh: MeshObject): seq[string] = + mesh.dirtyAttributes + +proc clearDirtyAttributes*(mesh: var MeshObject) = + mesh.dirtyAttributes.reset + +proc transform*[T: GPUType](mesh: var MeshObject, attribute: string, transform: Mat4) = + if mesh.vertexData.contains(attribute): + for i in 0 ..< mesh.vertexData[attribute].len: + setValue(mesh.vertexData[attribute], i, transform * getValue[T](mesh.vertexData[attribute], i)) + elif mesh.instanceData.contains(attribute): + for i in 0 ..< mesh.instanceData[attribute].len: + setValue(mesh.instanceData[attribute], i, transform * getValue[T](mesh.vertexData[attribute], i)) + else: + raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") + +proc applyTransformToVertices*(mesh: var MeshObject, positionAttribute=DEFAULT_POSITION_ATTRIBUTE) = + for i in 0 ..< mesh.vertexData[positionAttribute].len: + setValue(mesh.vertexData[positionAttribute], i, mesh.transform * getValue[Vec3f](mesh.vertexData[positionAttribute], i)) + mesh.transform = Unit4 + + +func getCollisionPoints*(mesh: MeshObject, positionAttribute=DEFAULT_POSITION_ATTRIBUTE): seq[Vec3f] = + for p in mesh[positionAttribute, Vec3f][]: + result.add mesh.transform * p + +func getCollider*(mesh: MeshObject, positionAttribute=DEFAULT_POSITION_ATTRIBUTE): Collider = + return mesh.getCollisionPoints(positionAttribute).calculateCollider(Points) + +proc asNonIndexedMesh*(mesh: MeshObject): MeshObject = + if mesh.indexType == None: + return mesh + + result = MeshObject( + vertexCount: mesh.indicesCount, + indexType: None, + transform: mesh.transform, + instanceTransforms: mesh.instanceTransforms, + visible: mesh.visible, + material: mesh.material + ) + for attribute, datalist in mesh.vertexData.pairs: + result.initVertexAttribute(attribute, datalist.theType) + for attribute, datalist in mesh.instanceData.pairs: + result.instanceData[attribute] = datalist.copy() + var i = 0 + case mesh.indexType + of Tiny: + for indices in mesh.tinyIndices: + for attribute, value in mesh.vertexData.pairs: + result.vertexData[attribute].appendFrom(i, mesh.vertexData[attribute], int(indices[0])) + result.vertexData[attribute].appendFrom(i + 1, mesh.vertexData[attribute], int(indices[1])) + result.vertexData[attribute].appendFrom(i + 2, mesh.vertexData[attribute], int(indices[2])) + i += 3 + of Small: + for indices in mesh.smallIndices: + for attribute, value in mesh.vertexData.pairs: + result.vertexData[attribute].appendFrom(i, value, int(indices[0])) + result.vertexData[attribute].appendFrom(i + 1, value, int(indices[1])) + result.vertexData[attribute].appendFrom(i + 2, value, int(indices[2])) + i += 3 + of Big: + for indices in mesh.bigIndices: + for attribute, value in mesh.vertexData.pairs: + result.vertexData[attribute].appendFrom(i, mesh.vertexData[attribute], int(indices[0])) + result.vertexData[attribute].appendFrom(i + 1, mesh.vertexData[attribute], int(indices[1])) + result.vertexData[attribute].appendFrom(i + 2, mesh.vertexData[attribute], int(indices[2])) + i += 3 + else: + discard + return result + + +# GENERATORS ============================================================================ + +proc rect*(width=1'f32, height=1'f32, color="ffffffff", material=EMPTY_MATERIAL.initMaterialData()): Mesh = + result = Mesh( + vertexCount: 4, + instanceTransforms: @[Unit4F32], + indexType: Small, + smallIndices: @[[0'u16, 1'u16, 2'u16], [2'u16, 3'u16, 0'u16]], + name: &"rect-{instanceCounter}", + material: material, + ) + inc instanceCounter + + let + half_w = width / 2 + half_h = height / 2 + pos = @[newVec3f(-half_w, -half_h), newVec3f( half_w, -half_h), newVec3f( half_w, half_h), newVec3f(-half_w, half_h)] + c = toRGBA(color) + + result[].initVertexAttribute(DEFAULT_POSITION_ATTRIBUTE, pos) + result[].initVertexAttribute("color", @[c, c, c, c]) + result[].initVertexAttribute("uv", @[newVec2f(0, 0), newVec2f(1, 0), newVec2f(1, 1), newVec2f(0, 1)]) + +proc tri*(width=1'f32, height=1'f32, color="ffffffff", material=EMPTY_MATERIAL.initMaterialData()): Mesh = + result = Mesh( + vertexCount: 3, + instanceTransforms: @[Unit4F32], + name: &"tri-{instanceCounter}", + material: material, + ) + inc instanceCounter + let + half_w = width / 2 + half_h = height / 2 + colorVec = toRGBA(color) + + result[].initVertexAttribute(DEFAULT_POSITION_ATTRIBUTE, @[newVec3f(0, -half_h), newVec3f( half_w, half_h), newVec3f(-half_w, half_h)]) + result[].initVertexAttribute("color", @[colorVec, colorVec, colorVec]) + +proc circle*(width=1'f32, height=1'f32, nSegments=12, color="ffffffff", material=EMPTY_MATERIAL.initMaterialData()): Mesh = + assert nSegments >= 3 + result = Mesh( + vertexCount: 3 + nSegments, + instanceTransforms: @[Unit4F32], + indexType: Small, + name: &"circle-{instanceCounter}", + material: material, + ) + inc instanceCounter + + let + half_w = width / 2 + half_h = height / 2 + c = toRGBA(color) + step = (2'f32 * PI) / float32(nSegments) + var + pos = @[newVec3f(0, 0), newVec3f(0, half_h)] + col = @[c, c] + for i in 0 .. nSegments: + pos.add newVec3f(cos(float32(i) * step) * half_w, sin(float32(i) * step) * half_h) + col.add c + result[].smallIndices.add [uint16(0), uint16(i + 1), uint16(i + 2)] + + result[].initVertexAttribute(DEFAULT_POSITION_ATTRIBUTE, pos) + result[].initVertexAttribute("color", col) + +# MESH TREES ============================================================================= + +type + MeshTree* = ref object + mesh*: Mesh + transform*: Mat4 = Unit4F32 + children*: seq[MeshTree] + +func toStringRec*(tree: MeshTree, theindent=0): seq[string] = + if tree.mesh.isNil: + result.add "*" + else: + result.add indent($tree.mesh, theindent) + for child in tree.children: + result.add child.toStringRec(theindent + 4) + +func `$`*(tree: MeshTree): string = + toStringRec(tree).join("\n") + + +proc toSeq*(tree: MeshTree): seq[Mesh] = + var queue = @[tree] + while queue.len > 0: + var current = queue.pop + if not current.mesh.isNil: + result.add current.mesh + queue.add current.children + +proc updateTransforms*(tree: MeshTree, parentTransform=Unit4F32) = + let currentTransform = parentTransform * tree.transform + if not tree.mesh.isNil: + tree.mesh.transform = currentTransform + for child in tree.children: + child.updateTransforms(currentTransform) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/noise.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/noise.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,34 @@ +import hashes +import math + +import ./core/vector + + +proc randomGradient(pos: Vec2f, seed: int32 = 0): Vec2f = + let randomAngle: float32 = TAU * (float32(int(hash((pos.x, pos.y, seed)))) / float32(high(int))) + return newVec2f(cos(randomAngle), sin(randomAngle)) + +proc interpolate(a: float32, b: float32, weight: float32): float32 = + # with Smootherstep + (b - a) * ((weight * (weight * 6.0 - 15.0) + 10.0) * weight * weight * weight) + a; + +proc perlin*(pos: Vec2f, seed: int32 = 0): float32 = + let + # grid coordinates around target point + topleft = newVec2f(trunc(pos.x), trunc(pos.y)) + topright = topleft + newVec2f(1, 0) + bottomleft = topleft + newVec2f(0, 1) + bottomright = topleft + newVec2f(1, 1) + # products for weights + topleft_dot = topleft.randomGradient(seed).dot((pos - topleft)) + topright_dot = topright.randomGradient(seed).dot((pos - topright)) + bottomleft_dot = bottomleft.randomGradient(seed).dot((pos - bottomleft)) + bottomright_dot = bottomright.randomGradient(seed).dot((pos - bottomright)) + xinterpol = pos.x - topleft.x + yinterpol = pos.y - topleft.y + + return interpolate( + interpolate(topleft_dot, bottomleft_dot, yinterpol), + interpolate(topright_dot, bottomright_dot, yinterpol), + xinterpol + ) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/audio.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/audio.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,6 @@ +when defined(linux): + include ./linux/audio +elif defined(windows): + include ./windows/audio + +export audio diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/linux/audio.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/linux/audio.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,68 @@ +import ../../core + +# alsa API +type + OpenMode*{.size: sizeof(culong).} = enum + SND_PCM_BLOCK = 0x00000000 # added by semicongine, for clarity + SND_PCM_NONBLOCK = 0x00000001 + StreamMode* {.size: sizeof(cint).} = enum + SND_PCM_STREAM_PLAYBACK = 0 + AccessMode*{.size: sizeof(cint).} = enum + SND_PCM_ACCESS_RW_INTERLEAVED = 3 + PCMFormat*{.size: sizeof(cint).} = enum + SND_PCM_FORMAT_S16_LE = 2 + snd_pcm_p* = ptr object + snd_pcm_hw_params_p* = ptr object + snd_pcm_uframes_t* = culong + snd_pcm_sframes_t* = clong +{.pragma: alsafunc, importc, cdecl, dynlib: "libasound.so.2" .} +proc snd_pcm_open*(pcm_ref: ptr snd_pcm_p, name: cstring, streamMode: StreamMode, openmode: OpenMode): cint {.alsafunc.} +proc snd_pcm_close*(pcm: snd_pcm_p): cint {.alsafunc.} +proc snd_pcm_hw_params_malloc*(hw_params_ptr: ptr snd_pcm_hw_params_p): cint {.alsafunc.} +proc snd_pcm_hw_params_free*(hw_params: snd_pcm_hw_params_p) {.alsafunc.} +proc snd_pcm_hw_params_any*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p): cint {.alsafunc.} +proc snd_pcm_hw_params_set_access*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, mode: AccessMode): cint {.alsafunc.} +proc snd_pcm_hw_params_set_format*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, format: PCMFormat): cint {.alsafunc.} +proc snd_pcm_hw_params_set_channels*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, val: cuint): cint {.alsafunc.} +proc snd_pcm_hw_params_set_buffer_size*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, size: snd_pcm_uframes_t): cint {.alsafunc.} +proc snd_pcm_hw_params_set_rate*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, val: cuint, dir: cint): cint {.alsafunc.} +proc snd_pcm_hw_params*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p): cint {.alsafunc.} +proc snd_pcm_writei*(pcm: snd_pcm_p, buffer: pointer, size: snd_pcm_uframes_t): snd_pcm_sframes_t {.alsafunc.} +proc snd_pcm_recover*(pcm: snd_pcm_p, err: cint, silent: cint): cint {.alsafunc.} + +template checkAlsaResult*(call: untyped) = + let value = call + if value < 0: + raise newException(Exception, "Alsa error: " & astToStr(call) & + " returned " & $value) + +# required for engine: + +type + NativeSoundDevice* = object + handle: snd_pcm_p + buffers: seq[ptr SoundData] + +proc openSoundDevice*(sampleRate: uint32, buffers: seq[ptr SoundData]): NativeSoundDevice = + var hw_params: snd_pcm_hw_params_p = nil + checkAlsaResult snd_pcm_open(addr result.handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_BLOCK) + + # hw parameters, quiet a bit of hardcoding here + checkAlsaResult snd_pcm_hw_params_malloc(addr hw_params) + checkAlsaResult snd_pcm_hw_params_any(result.handle, hw_params) + checkAlsaResult snd_pcm_hw_params_set_access(result.handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) + checkAlsaResult snd_pcm_hw_params_set_format(result.handle, hw_params, SND_PCM_FORMAT_S16_LE) + checkAlsaResult snd_pcm_hw_params_set_rate(result.handle, hw_params, sampleRate, 0) + checkAlsaResult snd_pcm_hw_params_set_channels(result.handle, hw_params, 2) + checkAlsaResult snd_pcm_hw_params_set_buffer_size(result.handle, hw_params, snd_pcm_uframes_t(buffers[0][].len)) + checkAlsaResult snd_pcm_hw_params(result.handle, hw_params) + snd_pcm_hw_params_free(hw_params) + result.buffers = buffers + +proc writeSoundData*(soundDevice: NativeSoundDevice, buffer: int) = + var ret = snd_pcm_writei(soundDevice.handle, addr soundDevice.buffers[buffer][][0], snd_pcm_uframes_t(soundDevice.buffers[buffer][].len)) + if ret < 0: + checkAlsaResult snd_pcm_recover(soundDevice.handle, cint(ret), 0) + +proc closeSoundDevice*(soundDevice: NativeSoundDevice) = + discard snd_pcm_close(soundDevice.handle) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/linux/surface.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/linux/surface.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,11 @@ +import ../../core +import ../../platform/window + +proc createNativeSurface*(instance: VkInstance, window: NativeWindow): VkSurfaceKHR = + assert instance.valid + var surfaceCreateInfo = VkXlibSurfaceCreateInfoKHR( + sType: VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, + dpy: cast[ptr vulkanapi.Display](window.display), + window: cast[vulkanapi.Window](window.window), + ) + checkVkResult vkCreateXlibSurfaceKHR(instance, addr(surfaceCreateInfo), nil, addr(result)) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/linux/symkey_map.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/linux/symkey_map.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,35 @@ +import std/tables +export tables + +import x11/x + + +import ../../events + +# got values (keycodes) from xev +const KeyTypeMap* = { + 9: Escape, 67: F1, 68: F2, 69: F3, 70: F4, 71: F5, 72: F6, 73: F7, 74: F8, + 75: F9, 76: F10, 95: F11, 96: F12, + 49: NumberRowExtra1, 10: `1`, 11: `2`, 12: `3`, 13: `4`, 14: `5`, 15: `6`, + 16: `7`, 17: `8`, 18: `9`, 19: `0`, 20: NumberRowExtra2, 21: NumberRowExtra3, + 24: Q, 25: W, 26: E, 27: R, 28: T, 29: Y, 30: U, 31: I, 32: O, 33: P, 38: A, + 39: S, 40: D, 41: Key.F, 42: G, 43: H, 44: J, 45: K, 46: L, 52: Z, 53: X, + 54: C, 55: V, 56: B, 57: N, 58: M, + + 23: Tab, 66: CapsLock, 50: ShiftL, 62: ShiftR, 37: CtrlL, 105: CtrlR, + 133: SuperL, 134: SuperR, + 64: AltL, 108: AltR, + 65: Space, 36: Enter, 22: Backspace, + 34: LetterRow1Extra1, 35: LetterRow1Extra2, + 47: LetterRow2Extra1, 48: LetterRow2Extra2, 51: LetterRow2Extra3, + 59: LetterRow3Extra1, 60: LetterRow3Extra2, 61: LetterRow3Extra3, + 111: Up, 116: Down, 113: Left, 114: Right, + 112: PageUp, 117: PageDown, 110: Home, 115: End, 118: Insert, 119: Delete, + 107: PrintScreen, 78: ScrollLock, 127: Pause, +}.toTable + +const MouseButtonTypeMap* = { + Button1: MouseButton.Mouse1, + Button2: MouseButton.Mouse2, + Button3: MouseButton.Mouse3, +}.toTable diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/linux/vulkanExtensions.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/linux/vulkanExtensions.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,1 @@ +const REQUIRED_PLATFORM_EXTENSIONS* = @["VK_KHR_xlib_surface"] diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/linux/window.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/linux/window.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,186 @@ +import std/options +import std/tables +import std/strformat +import std/logging + +import + x11/xlib, + x11/xutil, + x11/keysym, + x11/x, + x11/xkblib + +import ../../core +import ../../events + +import ./symkey_map + +export keysym + +var deleteMessage*: Atom + +type + NativeWindow* = object + display*: ptr xlib.Display + window*: x.Window + emptyCursor: Cursor + +template checkXlibResult*(call: untyped) = + let value = call + if value == 0: + raise newException(Exception, "Xlib error: " & astToStr(call) & + " returned " & $value) + +proc XErrorLogger(display: PDisplay, event: PXErrorEvent): cint {.cdecl.} = + error &"Xlib: {event[]}" + +proc createWindow*(title: string): NativeWindow = + checkXlibResult XInitThreads() + let display = XOpenDisplay(nil) + if display == nil: + quit "Failed to open display" + discard XSetErrorHandler(XErrorLogger) + + let rootWindow = display.XDefaultRootWindow() + discard display.XkbSetDetectableAutoRepeat(true, nil) + var + attribs: XWindowAttributes + width = cuint(800) + height = cuint(600) + checkXlibResult display.XGetWindowAttributes(rootWindow, addr(attribs)) + + var attrs = XSetWindowAttributes() + let window = XCreateWindow( + display, + rootWindow, + (attribs.width - cint(width)) div 2, (attribs.height - cint(height)) div 2, + width, height, + 0, + CopyFromParent, + InputOutput, + cast[PVisual](CopyFromParent), + 0, # CWOverrideRedirect, + addr attrs, + # foregroundColor, backgroundColor + ) + checkXlibResult XSetStandardProperties(display, window, title, "window", 0, nil, 0, nil) + checkXlibResult XSelectInput(display, window, PointerMotionMask or ButtonPressMask or ButtonReleaseMask or KeyPressMask or KeyReleaseMask or ExposureMask) + checkXlibResult XMapWindow(display, window) + + deleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", XBool(false)) + checkXlibResult XSetWMProtocols(display, window, addr(deleteMessage), 1) + + var data = "\0".cstring + var pixmap = display.XCreateBitmapFromData(window, data, 1, 1) + var color: XColor + var empty_cursor = display.XCreatePixmapCursor(pixmap, pixmap, addr(color), addr(color), 0, 0) + checkXlibResult display.XFreePixmap(pixmap) + return NativeWindow(display: display, window: window, emptyCursor: empty_cursor) + +proc fullscreen*(window: var NativeWindow, enable: bool) = + var + wm_state = window.display.XInternAtom("_NET_WM_STATE", 0) + wm_fullscreen = window.display.XInternAtom("_NET_WM_STATE_FULLSCREEN", 0) + var + xev: XEvent + xev.xclient = XClientMessageEvent( + message_type: wm_state, + format: 32, + window: window.window, + data: XClientMessageData( + l: [ + int(not enable) xor 1, + clong(wm_fullscreen), + 0, + 0, + 0 + ] + ) + ) + xev.theType = ClientMessage + + checkXlibResult window.display.XSendEvent( + window.display.DefaultRootWindow(), + 0, + SubstructureRedirectMask or SubstructureNotifyMask, + addr xev + ) + checkXlibResult window.display.XFlush() + +proc hideSystemCursor*(window: NativeWindow) = + checkXlibResult XDefineCursor(window.display, window.window, window.emptyCursor) + checkXlibResult window.display.XFlush() + +proc showSystemCursor*(window: NativeWindow) = + checkXlibResult XUndefineCursor(window.display, window.window) + checkXlibResult window.display.XFlush() + +proc destroy*(window: NativeWindow) = + checkXlibResult window.display.XFreeCursor(window.emptyCursor) + checkXlibResult window.display.XDestroyWindow(window.window) + discard window.display.XCloseDisplay() # always returns 0 + +proc size*(window: NativeWindow): (int, int) = + var attribs: XWindowAttributes + checkXlibResult XGetWindowAttributes(window.display, window.window, addr(attribs)) + return (int(attribs.width), int(attribs.height)) + +proc pendingEvents*(window: NativeWindow): seq[Event] = + var event: XEvent + while window.display.XPending() > 0: + discard window.display.XNextEvent(addr(event)) + case event.theType + of ClientMessage: + if cast[Atom](event.xclient.data.l[0]) == deleteMessage: + result.add(Event(eventType: Quit)) + of KeyPress: + let keyevent = cast[PXKeyEvent](addr(event)) + let xkey = int(keyevent.keycode) + result.add Event(eventType: KeyPressed, key: KeyTypeMap.getOrDefault(xkey, Key.UNKNOWN)) + of KeyRelease: + let keyevent = cast[PXKeyEvent](addr(event)) + let xkey = int(keyevent.keycode) + result.add Event(eventType: KeyReleased, key: KeyTypeMap.getOrDefault(xkey, Key.UNKNOWN)) + of ButtonPress: + let button = int(cast[PXButtonEvent](addr(event)).button) + if button == Button4: + result.add Event(eventType: MouseWheel, amount: 1'f32) + elif button == Button5: + result.add Event(eventType: MouseWheel, amount: -1'f32) + else: + result.add Event(eventType: MousePressed, button: MouseButtonTypeMap.getOrDefault(button, MouseButton.UNKNOWN)) + of ButtonRelease: + let button = int(cast[PXButtonEvent](addr(event)).button) + result.add Event(eventType: MouseReleased, button: MouseButtonTypeMap.getOrDefault(button, MouseButton.UNKNOWN)) + of MotionNotify: + let motion = cast[PXMotionEvent](addr(event)) + result.add Event(eventType: MouseMoved, x: motion.x, y: motion.y) + of ConfigureNotify, Expose: + result.add Event(eventType: ResizedWindow) + else: + discard + + +proc getMousePosition*(window: NativeWindow): Option[Vec2f] = + var + root: x.Window + win: x.Window + rootX: cint + rootY: cint + winX: cint + winY: cint + mask: cuint + onscreen = XQueryPointer( + window.display, + window.window, + addr(root), + addr(win), + addr(rootX), + addr(rootY), + addr(winX), + addr(winY), + addr(mask), + ) + if onscreen != 0: + result = some(Vec2f([float32(winX), float32(winY)])) + diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/surface.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/surface.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,6 @@ +when defined(linux): + import ../platform/linux/surface +elif defined(windows): + import ../platform/windows/surface + +export surface diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/vulkanExtensions.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/vulkanExtensions.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,6 @@ +when defined(linux): + include ./linux/vulkanExtensions +elif defined(windows): + include ./windows/vulkanExtensions + +export vulkanExtensions diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/window.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/window.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,6 @@ +when defined(linux): + include ./linux/window +elif defined(windows): + include ./windows/window + +export window diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/windows/audio.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/windows/audio.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,46 @@ +import winim +import winim/extra + +import ../../core/audiotypes + +template checkWinMMResult*(call: untyped) = + let value = call + if value < 0: + raise newException(Exception, "Windows multimedia error: " & astToStr(call) & + " returned " & $value) +type + NativeSoundDevice* = object + handle: HWAVEOUT + buffers: seq[WAVEHDR] + +proc openSoundDevice*(sampleRate: uint32, buffers: seq[ptr SoundData]): NativeSoundDevice = + var format = WAVEFORMATEX( + wFormatTag: WAVE_FORMAT_PCM, + nChannels: 2, + nSamplesPerSec: DWORD(sampleRate), + nAvgBytesPerSec: DWORD(sampleRate) * 4, + nBlockAlign: 4, + wBitsPerSample: 16, + cbSize: 0, + ) + checkWinMMResult waveOutOpen(addr result.handle, WAVE_MAPPER, addr format, DWORD_PTR(0), DWORD_PTR(0), CALLBACK_NULL) + + for i in 0 ..< buffers.len: + result.buffers.add WAVEHDR( + lpData: cast[cstring](addr buffers[i][][0]), + dwBufferLength: DWORD(buffers[i][].len * sizeof(Sample)), + dwLoops: 1, + ) + for i in 0 ..< result.buffers.len: + checkWinMMResult waveOutPrepareHeader(result.handle, addr result.buffers[i], UINT(sizeof(WAVEHDR))) + checkWinMMResult waveOutWrite(result.handle, addr result.buffers[i], UINT(sizeof(WAVEHDR))) + +proc writeSoundData*(soundDevice: var NativeSoundDevice, buffer: int) = + while (soundDevice.buffers[buffer].dwFlags and WHDR_DONE) == 0: + echo "" # ugly solution to prevent code elimination, need to find a nicer solution + checkWinMMResult waveOutWrite(soundDevice.handle, addr soundDevice.buffers[buffer], UINT(sizeof(WAVEHDR))) + +proc closeSoundDevice*(soundDevice: var NativeSoundDevice) = + for i in 0 ..< soundDevice.buffers.len: + discard waveOutUnprepareHeader(soundDevice.handle, addr soundDevice.buffers[i], UINT(sizeof(WAVEHDR))) + waveOutClose(soundDevice.handle) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/windows/surface.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/windows/surface.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,11 @@ +import ../../core +import ../../platform/window + +proc createNativeSurface*(instance: VkInstance, window: NativeWindow): VkSurfaceKHR = + assert instance.valid + var surfaceCreateInfo = VkWin32SurfaceCreateInfoKHR( + sType: VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, + hinstance: cast[HINSTANCE](window.hinstance), + hwnd: cast[HWND](window.hwnd), + ) + checkVkResult vkCreateWin32SurfaceKHR(instance, addr(surfaceCreateInfo), nil, addr(result)) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/windows/virtualkey_map.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/windows/virtualkey_map.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,33 @@ +import std/tables +export tables + +import winim/core + +import ../../events + +const KeyTypeMap* = { + VK_ESCAPE: Key.Escape, VK_F1: F1, VK_F2: F2, VK_F3: F3, VK_F4: F4, VK_F5: F5, + VK_F6: F6, VK_F7: F7, VK_F8: F8, VK_F9: F9, VK_F10: F10, VK_F11: F11, + VK_F12: F12, + VK_OEM_3: NumberRowExtra1, int('0'): `0`, int('1'): `1`, int('2'): `2`, int( + '3'): `3`, int('4'): `4`, int('5'): `5`, int('6'): `6`, int('7'): `7`, + int('8'): `8`, int('9'): `9`, VK_OEM_MINUS: NumberRowExtra2, + VK_OEM_PLUS: NumberRowExtra3, + int('A'): A, int('B'): B, int('C'): C, int('D'): D, int('E'): E, int('F'): F, + int('G'): G, int('H'): H, int('I'): I, int('J'): J, int('K'): K, int( + 'L'): L, int('M'): M, int('N'): N, int('O'): O, int('P'): P, int('Q'): Q, + int('R'): R, int('S'): S, int('T'): T, int('U'): U, int('V'): V, int( + 'W'): W, int('X'): X, int('Y'): Y, int('Z'): Z, + VK_TAB: Tab, VK_CAPITAL: CapsLock, VK_LSHIFT: ShiftL, VK_SHIFT: ShiftL, + VK_RSHIFT: ShiftR, VK_LCONTROL: CtrlL, VK_CONTROL: CtrlL, + VK_RCONTROL: CtrlR, VK_LWIN: SuperL, VK_RWIN: SuperR, VK_LMENU: AltL, + VK_RMENU: AltR, VK_SPACE: Space, VK_RETURN: Enter, VK_BACK: Backspace, + VK_OEM_4: LetterRow1Extra1, VK_OEM_6: LetterRow1Extra2, + VK_OEM_5: LetterRow2Extra3, + VK_OEM_1: LetterRow2Extra1, VK_OEM_7: LetterRow2Extra2, + VK_OEM_COMMA: LetterRow3Extra1, VK_OEM_PERIOD: LetterRow3Extra2, + VK_OEM_2: LetterRow3Extra3, + VK_UP: Up, VK_DOWN: Down, VK_LEFT: Left, VK_RIGHT: Right, + VK_PRIOR: PageUp, VK_NEXT: PageDown, VK_HOME: Home, VK_END: End, + VK_INSERT: Insert, VK_DELETE: Key.Delete, +}.toTable diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/windows/vulkanExtensions.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/windows/vulkanExtensions.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,1 @@ +const REQUIRED_PLATFORM_EXTENSIONS* = @["VK_KHR_win32_surface"] diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/platform/windows/window.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/platform/windows/window.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,139 @@ +import std/options +import winim + +import ../../core/vector +import ./virtualkey_map +import ../../events + +type + NativeWindow* = object + hinstance*: HINSTANCE + hwnd*: HWND + g_wpPrev: WINDOWPLACEMENT + + +# sorry, have to use module-global variable to capture windows events +var currentEvents: seq[Event] + +template checkWin32Result*(call: untyped) = + let value = call + if value == 0: + raise newException(Exception, "Win32 error: " & astToStr(call) & " returned " & $value) + + +proc MapLeftRightKeys(key: INT, lparam: LPARAM): INT = + case key + of VK_SHIFT: + MapVirtualKey(UINT((lParam and 0x00ff0000) shr 16), MAPVK_VSC_TO_VK_EX) + of VK_CONTROL: + if (lParam and 0x01000000) == 0: VK_LCONTROL else: VK_RCONTROL + of VK_MENU: + if (lParam and 0x01000000) == 0: VK_LMENU else: VK_RMENU + else: + key + +proc WindowHandler(hwnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} = + case uMsg + of WM_DESTROY: + currentEvents.add(Event(eventType: events.EventType.Quit)) + of WM_KEYDOWN, WM_SYSKEYDOWN: + let key = MapLeftRightKeys(INT(wParam), lParam) + currentEvents.add(Event(eventType: KeyPressed, key: KeyTypeMap.getOrDefault(key, Key.UNKNOWN))) + of WM_KEYUP, WM_SYSKEYUP: + let key = MapLeftRightKeys(INT(wParam), lParam) + currentEvents.add(Event(eventType: KeyReleased, key: KeyTypeMap.getOrDefault(key, Key.UNKNOWN))) + of WM_LBUTTONDOWN: + currentEvents.add(Event(eventType: MousePressed, button: MouseButton.Mouse1)) + of WM_LBUTTONUP: + currentEvents.add(Event(eventType: MouseReleased, button: MouseButton.Mouse1)) + of WM_MBUTTONDOWN: + currentEvents.add(Event(eventType: MousePressed, button: MouseButton.Mouse2)) + of WM_MBUTTONUP: + currentEvents.add(Event(eventType: MouseReleased, button: MouseButton.Mouse2)) + of WM_RBUTTONDOWN: + currentEvents.add(Event(eventType: MousePressed, button: MouseButton.Mouse3)) + of WM_RBUTTONUP: + currentEvents.add(Event(eventType: MouseReleased, button: MouseButton.Mouse3)) + of WM_MOUSEMOVE: + currentEvents.add(Event(eventType: events.MouseMoved, x: GET_X_LPARAM(lParam), y: GET_Y_LPARAM(lParam))) + of WM_MOUSEWHEEL: + currentEvents.add(Event(eventType: events.MouseWheel, amount: float32(GET_WHEEL_DELTA_WPARAM(wParam)) / WHEEL_DELTA)) + else: + return DefWindowProc(hwnd, uMsg, wParam, lParam) + + +proc createWindow*(title: string): NativeWindow = + result.hInstance = HINSTANCE(GetModuleHandle(nil)) + var + windowClassName = T"EngineWindowClass" + windowName = T(title) + windowClass = WNDCLASSEX( + cbSize: UINT(WNDCLASSEX.sizeof), + lpfnWndProc: WindowHandler, + hInstance: result.hInstance, + lpszClassName: windowClassName, + hcursor: LoadCursor(HINSTANCE(0), IDC_ARROW), + ) + + if(RegisterClassEx(addr(windowClass)) == 0): + raise newException(Exception, "Unable to register window class") + + result.hwnd = CreateWindowEx( + DWORD(0), + windowClassName, + windowName, + DWORD(WS_OVERLAPPEDWINDOW), + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + HMENU(0), + HINSTANCE(0), + result.hInstance, + nil + ) + + result.g_wpPrev.length = UINT(sizeof(WINDOWPLACEMENT)) + discard ShowWindow(result.hwnd, SW_SHOW) + +# inspired by the one and only, Raymond Chen +# https://devblogs.microsoft.com/oldnewthing/20100412-00/?p=14353 +proc fullscreen*(window: var NativeWindow, enable: bool) = + let dwStyle: DWORD = GetWindowLong(window.hwnd, GWL_STYLE) + if enable: + var mi = MONITORINFO(cbSize: DWORD(sizeof(MONITORINFO))) + if GetWindowPlacement(window.hwnd, addr window.g_wpPrev) and GetMonitorInfo(MonitorFromWindow(window.hwnd, MONITOR_DEFAULTTOPRIMARY), addr mi): + SetWindowLong(window.hwnd, GWL_STYLE, dwStyle and (not WS_OVERLAPPEDWINDOW)) + SetWindowPos(window.hwnd, HWND_TOP, mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top, SWP_NOOWNERZORDER or SWP_FRAMECHANGED) + else: + SetWindowLong(window.hwnd, GWL_STYLE, dwStyle or WS_OVERLAPPEDWINDOW) + SetWindowPlacement(window.hwnd, addr window.g_wpPrev) + SetWindowPos(window.hwnd, HWND(0), 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_NOOWNERZORDER or SWP_FRAMECHANGED) + +proc hideSystemCursor*(window: NativeWindow) = + discard ShowCursor(false) + +proc showSystemCursor*(window: NativeWindow) = + discard ShowCursor(true) + +proc destroy*(window: NativeWindow) = + discard + +proc size*(window: NativeWindow): (int, int) = + var rect: RECT + checkWin32Result GetWindowRect(window.hwnd, addr(rect)) + (int(rect.right - rect.left), int(rect.bottom - rect.top)) + +proc pendingEvents*(window: NativeWindow): seq[Event] = + # empty queue + currentEvents = newSeq[Event]() + var msg: MSG + # fill queue + while PeekMessage(addr(msg), window.hwnd, 0, 0, PM_REMOVE): + TranslateMessage(addr(msg)) + DispatchMessage(addr(msg)) + return currentEvents + +proc getMousePosition*(window: NativeWindow): Option[Vec2f] = + var p: POINT + let res = GetCursorPos(addr(p)) + if res: + return some(Vec2f([float32(p.x), float32(p.y)])) + return none(Vec2f) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/renderer.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/renderer.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,508 @@ +import std/options +import std/tables +import std/strformat +import std/sequtils +import std/strutils +import std/logging + +import ./core +import ./vulkan/buffer +import ./vulkan/device +import ./vulkan/drawable +import ./vulkan/physicaldevice +import ./vulkan/pipeline +import ./vulkan/renderpass +import ./vulkan/swapchain +import ./vulkan/shader +import ./vulkan/descriptor +import ./vulkan/image + +import ./scene +import ./mesh +import ./material + +const TRANSFORM_ATTRIBUTE = "transform" +const MATERIALINDEX_ATTRIBUTE = "materialIndex" +const VERTEX_ATTRIB_ALIGNMENT = 4 # used for buffer alignment + +type + SceneData = ref object + drawables*: seq[tuple[drawable: Drawable, mesh: Mesh]] + vertexBuffers*: Table[MemoryPerformanceHint, Buffer] + indexBuffer*: Buffer + uniformBuffers*: Table[VkPipeline, seq[Buffer]] # one per frame-in-flight + textures*: Table[VkPipeline, Table[string, seq[VulkanTexture]]] # per frame-in-flight + attributeLocation*: Table[string, MemoryPerformanceHint] + vertexBufferOffsets*: Table[(Mesh, string), int] + descriptorPools*: Table[VkPipeline, DescriptorPool] + descriptorSets*: Table[VkPipeline, seq[DescriptorSet]] + materials: Table[MaterialType, seq[MaterialData]] + Renderer* = object + device: Device + surfaceFormat: VkSurfaceFormatKHR + renderPass: RenderPass + swapchain: Swapchain + scenedata: Table[Scene, SceneData] + emptyTexture: VulkanTexture + +proc initRenderer*(device: Device, shaders: openArray[(MaterialType, ShaderConfiguration)], clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32]), backFaceCulling=true): Renderer = + assert device.vk.valid + + result.device = device + result.renderPass = device.simpleForwardRenderPass(shaders, clearColor=clearColor, backFaceCulling=backFaceCulling) + result.surfaceFormat = device.physicalDevice.getSurfaceFormats().filterSurfaceFormat() + # use last renderpass as output for swapchain + let swapchain = device.createSwapchain(result.renderPass.vk, result.surfaceFormat, device.firstGraphicsQueue().get().family) + if not swapchain.isSome: + raise newException(Exception, "Unable to create swapchain") + + result.swapchain = swapchain.get() + result.emptyTexture = device.uploadTexture(EMPTYTEXTURE) + +func inputs(renderer: Renderer, scene: Scene): seq[ShaderAttribute] = + var found: Table[string, ShaderAttribute] + for i in 0 ..< renderer.renderPass.subpasses.len: + for (materialType, shaderPipeline) in renderer.renderPass.subpasses[i].shaderPipelines: + if scene.usesMaterial(materialType): + for input in shaderPipeline.inputs: + if found.contains(input.name): + assert input.name == found[input.name].name, &"{input.name}: {input.name} != {found[input.name].name}" + assert input.theType == found[input.name].theType, &"{input.name}: {input.theType} != {found[input.name].theType}" + assert input.arrayCount == found[input.name].arrayCount, &"{input.name}: {input.arrayCount} != {found[input.name].arrayCount}" + assert input.memoryPerformanceHint == found[input.name].memoryPerformanceHint, &"{input.name}: {input.memoryPerformanceHint} != {found[input.name].memoryPerformanceHint}" + else: + result.add input + found[input.name] = input + +func materialCompatibleWithPipeline(scene: Scene, materialType: MaterialType, shaderPipeline: ShaderPipeline): (bool, string) = + for uniform in shaderPipeline.uniforms: + if scene.shaderGlobals.contains(uniform.name): + if scene.shaderGlobals[uniform.name].theType != uniform.theType: + return (true, &"shader uniform needs type {uniform.theType} but scene global is of type {scene.shaderGlobals[uniform.name].theType}") + else: + var foundMatch = true + for name, theType in materialType.attributes.pairs: + if name == uniform.name and theType == uniform.theType: + foundMatch = true + break + if not foundMatch: + return (true, &"shader uniform '{uniform.name}' was not found in scene globals or scene materials") + for texture in shaderPipeline.samplers: + if scene.shaderGlobals.contains(texture.name): + if scene.shaderGlobals[texture.name].theType != texture.theType: + return (true, &"shader texture '{texture.name}' needs type {texture.theType} but scene global is of type {scene.shaderGlobals[texture.name].theType}") + else: + var foundMatch = true + for name in materialType.attributes.keys: + if name == texture.name: + foundMatch = true + break + if not foundMatch: + return (true, &"Required texture for shader texture '{texture.name}' was not found in scene materials") + + return (false, "") + +func meshCompatibleWithPipeline(scene: Scene, mesh: Mesh, shaderPipeline: ShaderPipeline): (bool, string) = + for input in shaderPipeline.inputs: + if input.name in [TRANSFORM_ATTRIBUTE, MATERIALINDEX_ATTRIBUTE]: # will be populated automatically + assert input.perInstance == true, &"Currently the {input.name} attribute must be a per instance attribute" + continue + if not (input.name in mesh[].attributes): + return (true, &"Shader input '{input.name}' is not available for mesh") + if input.theType != mesh[].attributeType(input.name): + return (true, &"Shader input '{input.name}' expects type {input.theType}, but mesh has {mesh[].attributeType(input.name)}") + if not input.perInstance and not mesh[].vertexAttributes.contains(input.name): + return (true, &"Shader input '{input.name}' expected to be vertex attribute, but mesh has no such vertex attribute (available are: {mesh[].vertexAttributes})") + if input.perInstance and not mesh[].instanceAttributes.contains(input.name): + return (true, &"Shader input '{input.name}' expected to be per instance attribute, but mesh has no such instance attribute (available are: {mesh[].instanceAttributes})") + + let pipelineCompatability = scene.materialCompatibleWithPipeline(mesh.material.theType, shaderPipeline) + if pipelineCompatability[0]: + return (true, pipelineCompatability[1]) + return (false, "") + +func checkSceneIntegrity(renderer: Renderer, scene: Scene) = + # TODO: this and the sub-functions can likely be simplified a ton + if scene.meshes.len == 0: + return + + var foundRenderableObject = false + var materialTypes: seq[MaterialType] + for i in 0 ..< renderer.renderPass.subpasses.len: + for (materialType, shaderPipeline) in renderer.renderPass.subpasses[i].shaderPipelines: + materialTypes.add materialType + for mesh in scene.meshes: + if mesh.material.theType == materialType: + foundRenderableObject = true + let (error, message) = scene.meshCompatibleWithPipeline(mesh, shaderPipeline) + assert not error, &"Mesh '{mesh}' not compatible with assigned shaderPipeline ({materialType}) because: {message}" + + if not foundRenderableObject: + var matTypes: Table[string, MaterialType] + for mesh in scene.meshes: + if not matTypes.contains(mesh.material.name): + matTypes[mesh.material.name] = mesh.material.theType + assert false, &"Scene '{scene.name}' has been added but materials are not compatible with any registered shader: Materials in scene: {matTypes}, registered shader-materialtypes: {materialTypes}" + +proc setupDrawableBuffers*(renderer: var Renderer, scene: var Scene) = + assert not (scene in renderer.scenedata) + + var scenedata = SceneData() + + # find all material data and group it by material type + for mesh in scene.meshes: + if not scenedata.materials.contains(mesh.material.theType): + scenedata.materials[mesh.material.theType] = @[] + if not scenedata.materials[mesh.material.theType].contains(mesh.material): + scenedata.materials[mesh.material.theType].add mesh.material + + # automatically populate material and tranform attributes + for mesh in scene.meshes: + if not (TRANSFORM_ATTRIBUTE in mesh[].attributes): + mesh[].initInstanceAttribute(TRANSFORM_ATTRIBUTE, Unit4) + if not (MATERIALINDEX_ATTRIBUTE in mesh[].attributes): + mesh[].initInstanceAttribute(MATERIALINDEX_ATTRIBUTE, uint16(scenedata.materials[mesh.material.theType].find(mesh.material))) + + renderer.checkSceneIntegrity(scene) + + let inputs = renderer.inputs(scene) + + # create index buffer if necessary + var indicesBufferSize = 0 + for mesh in scene.meshes: + if mesh[].indexType != MeshIndexType.None: + let indexAlignment = case mesh[].indexType + of MeshIndexType.None: 0 + of Tiny: 1 + of Small: 2 + of Big: 4 + # index value alignment required by Vulkan + if indicesBufferSize mod indexAlignment != 0: + indicesBufferSize += indexAlignment - (indicesBufferSize mod indexAlignment) + indicesBufferSize += mesh[].indexSize + if indicesBufferSize > 0: + scenedata.indexBuffer = renderer.device.createBuffer( + size=indicesBufferSize, + usage=[VK_BUFFER_USAGE_INDEX_BUFFER_BIT], + requireMappable=false, + preferVRAM=true, + ) + + # calculcate offsets for attributes in vertex buffers + # trying to use one buffer per memory type + var perLocationSizes: Table[MemoryPerformanceHint, int] + for hint in MemoryPerformanceHint: + perLocationSizes[hint] = 0 + for attribute in inputs: + scenedata.attributeLocation[attribute.name] = attribute.memoryPerformanceHint + # setup one buffer per attribute-location-type + for mesh in scene.meshes: + # align size to VERTEX_ATTRIB_ALIGNMENT bytes (the important thing is the correct alignment of the offsets, but + # we need to expand the buffer size as well, therefore considering alignment already here as well + if perLocationSizes[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT != 0: + perLocationSizes[attribute.memoryPerformanceHint] += VERTEX_ATTRIB_ALIGNMENT - (perLocationSizes[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT) + perLocationSizes[attribute.memoryPerformanceHint] += mesh[].attributeSize(attribute.name) + + # create vertex buffers + for memoryPerformanceHint, bufferSize in perLocationSizes.pairs: + if bufferSize > 0: + scenedata.vertexBuffers[memoryPerformanceHint] = renderer.device.createBuffer( + size=bufferSize, + usage=[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT], + requireMappable=memoryPerformanceHint==PreferFastWrite, + preferVRAM=true, + ) + + # calculate offset of each attribute for all meshes + var perLocationOffsets: Table[MemoryPerformanceHint, int] + var indexBufferOffset = 0 + for hint in MemoryPerformanceHint: + perLocationOffsets[hint] = 0 + + for mesh in scene.meshes: + for attribute in inputs: + scenedata.vertexBufferOffsets[(mesh, attribute.name)] = perLocationOffsets[attribute.memoryPerformanceHint] + if mesh[].attributes.contains(attribute.name): + let size = mesh[].getRawData(attribute.name)[1] + perLocationOffsets[attribute.memoryPerformanceHint] += size + if perLocationOffsets[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT != 0: + perLocationOffsets[attribute.memoryPerformanceHint] += VERTEX_ATTRIB_ALIGNMENT - (perLocationOffsets[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT) + + # fill offsets per shaderPipeline (as sequence corresponds to shader input binding) + var offsets: Table[VkPipeline, seq[(string, MemoryPerformanceHint, int)]] + for subpass_i in 0 ..< renderer.renderPass.subpasses.len: + for (materialType, shaderPipeline) in renderer.renderPass.subpasses[subpass_i].shaderPipelines: + if scene.usesMaterial(materialType): + offsets[shaderPipeline.vk] = newSeq[(string, MemoryPerformanceHint, int)]() + for attribute in shaderPipeline.inputs: + offsets[shaderPipeline.vk].add (attribute.name, attribute.memoryPerformanceHint, scenedata.vertexBufferOffsets[(mesh, attribute.name)]) + + # create drawables + let indexed = mesh.indexType != MeshIndexType.None + var drawable = Drawable( + name: mesh.name, + elementCount: if indexed: mesh[].indicesCount else: mesh[].vertexCount, + bufferOffsets: offsets, + instanceCount: mesh[].instanceCount, + indexed: indexed, + ) + if indexed: + let indexAlignment = case mesh.indexType + of MeshIndexType.None: 0 + of Tiny: 1 + of Small: 2 + of Big: 4 + # index value alignment required by Vulkan + if indexBufferOffset mod indexAlignment != 0: + indexBufferOffset += indexAlignment - (indexBufferOffset mod indexAlignment) + drawable.indexBufferOffset = indexBufferOffset + drawable.indexType = mesh.indexType + var (pdata, size) = mesh[].getRawIndexData() + scenedata.indexBuffer.setData(pdata, size, indexBufferOffset) + indexBufferOffset += size + scenedata.drawables.add (drawable, mesh) + + # setup uniforms and textures (anything descriptor) + var uploadedTextures: Table[Texture, VulkanTexture] + for subpass_i in 0 ..< renderer.renderPass.subpasses.len: + for (materialType, shaderPipeline) in renderer.renderPass.subpasses[subpass_i].shaderPipelines: + if scene.usesMaterial(materialType): + # gather textures + scenedata.textures[shaderPipeline.vk] = initTable[string, seq[VulkanTexture]]() + for texture in shaderPipeline.samplers: + scenedata.textures[shaderPipeline.vk][texture.name] = newSeq[VulkanTexture]() + if scene.shaderGlobals.contains(texture.name): + for textureValue in getValues[Texture](scene.shaderGlobals[texture.name])[]: + if not uploadedTextures.contains(textureValue): + uploadedTextures[textureValue] = renderer.device.uploadTexture(textureValue) + scenedata.textures[shaderPipeline.vk][texture.name].add uploadedTextures[textureValue] + else: + var foundTexture = false + for material in scene.getMaterials(materialType): + for materialAttribName, value in material.attributes.pairs: + if materialAttribName == texture.name: + if not foundTexture: + foundTexture = true + assert value.theType == TextureType, &"Mesh material has attribute '{materialAttribName}' which is expected to be of type 'Texture' but is of type {value.theType}" + assert value.len == 1, &"Mesh material attribute '{materialAttribName}' has texture-array, but only single textures are allowed" + let textureValue = getValues[Texture](value)[][0] + if not uploadedTextures.contains(textureValue): + uploadedTextures[textureValue] = renderer.device.uploadTexture(textureValue) + scenedata.textures[shaderPipeline.vk][texture.name].add uploadedTextures[textureValue] + break + assert foundTexture, &"No texture found in shaderGlobals or materials for '{texture.name}'" + let nTextures = scenedata.textures[shaderPipeline.vk][texture.name].len + assert (texture.arrayCount == 0 and nTextures == 1) or texture.arrayCount == nTextures, &"Shader assigned to render '{materialType}' expected {texture.arrayCount} textures for '{texture.name}' but got {nTextures}" + + # gather uniform sizes + var uniformBufferSize = 0 + for uniform in shaderPipeline.uniforms: + uniformBufferSize += uniform.size + if uniformBufferSize > 0: + scenedata.uniformBuffers[shaderPipeline.vk] = newSeq[Buffer]() + for frame_i in 0 ..< renderer.swapchain.inFlightFrames: + scenedata.uniformBuffers[shaderPipeline.vk].add renderer.device.createBuffer( + size=uniformBufferSize, + usage=[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT], + requireMappable=true, + preferVRAM=true, + ) + + # setup descriptors + var poolsizes = @[(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, renderer.swapchain.inFlightFrames)] + if scenedata.textures[shaderPipeline.vk].len > 0: + var textureCount = 0 + for textures in scenedata.textures[shaderPipeline.vk].values: + textureCount += textures.len + poolsizes.add (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, renderer.swapchain.inFlightFrames * textureCount * 2) + + scenedata.descriptorPools[shaderPipeline.vk] = renderer.device.createDescriptorSetPool(poolsizes) + + scenedata.descriptorSets[shaderPipeline.vk] = shaderPipeline.setupDescriptors( + scenedata.descriptorPools[shaderPipeline.vk], + scenedata.uniformBuffers.getOrDefault(shaderPipeline.vk, @[]), + scenedata.textures[shaderPipeline.vk], + inFlightFrames=renderer.swapchain.inFlightFrames, + emptyTexture=renderer.emptyTexture, + ) + for frame_i in 0 ..< renderer.swapchain.inFlightFrames: + scenedata.descriptorSets[shaderPipeline.vk][frame_i].writeDescriptorSet() + + renderer.scenedata[scene] = scenedata + +proc refreshMeshAttributeData(renderer: Renderer, scene: var Scene, drawable: Drawable, mesh: Mesh, attribute: string) = + debug &"Refreshing data on mesh mesh for {attribute}" + # ignore attributes that are not used in this shader + if not (attribute in renderer.scenedata[scene].attributeLocation): + return + + let (pdata, size) = mesh[].getRawData(attribute) + let memoryPerformanceHint = renderer.scenedata[scene].attributeLocation[attribute] + renderer.scenedata[scene].vertexBuffers[memoryPerformanceHint].setData(pdata, size, renderer.scenedata[scene].vertexBufferOffsets[(mesh, attribute)]) + +proc updateMeshData*(renderer: var Renderer, scene: var Scene, forceAll=false) = + assert scene in renderer.scenedata + + for (drawable, mesh) in renderer.scenedata[scene].drawables.mitems: + if mesh[].attributes.contains(TRANSFORM_ATTRIBUTE): + mesh[].updateInstanceTransforms(TRANSFORM_ATTRIBUTE) + let attrs = (if forceAll: mesh[].attributes else: mesh[].dirtyAttributes) + for attribute in attrs: + renderer.refreshMeshAttributeData(scene, drawable, mesh, attribute) + debug &"Update mesh attribute {attribute}" + mesh[].clearDirtyAttributes() + +proc updateUniformData*(renderer: var Renderer, scene: var Scene, forceAll=false) = + assert scene in renderer.scenedata + # TODO: maybe check for dirty materials too, but atm we copy materials into the + # renderers scenedata, so they are immutable after initialization, would + # need to allow updates of materials too in order to make sense + + let dirty = scene.dirtyShaderGlobals + if not forceAll and dirty.len == 0: + return + + if forceAll: + debug "Update uniforms because 'forceAll' was given" + else: + debug &"Update uniforms because of dirty scene globals: {dirty}" + + # loop over all used shaders/pipelines + for i in 0 ..< renderer.renderPass.subpasses.len: + for (materialType, shaderPipeline) in renderer.renderPass.subpasses[i].shaderPipelines: + if ( + scene.usesMaterial(materialType) and + renderer.scenedata[scene].uniformBuffers.hasKey(shaderPipeline.vk) and + renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk].len != 0 + ): + assert renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk][renderer.swapchain.currentInFlight].vk.valid + if forceAll: + for buffer in renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk]: + assert buffer.vk.valid + + var offset = 0 + # loop over all uniforms of the shader-shaderPipeline + for uniform in shaderPipeline.uniforms: + if dirty.contains(uniform.name) or forceAll: # only update if necessary + var value: DataList + if scene.shaderGlobals.hasKey(uniform.name): + assert scene.shaderGlobals[uniform.name].thetype == uniform.thetype + value = scene.shaderGlobals[uniform.name] + else: + var foundValue = false + for material in renderer.scenedata[scene].materials[materialType]: + for name, materialValue in material.attributes.pairs: + if uniform.name == name: + if not foundValue: + foundValue = true + value = initDataList(materialValue.theType, 0) + else: + assert value.theType == materialValue.theType, &"Material for uniform '{uniform.name}' was found multiple times with different types: {value.theType} and {materialValue.theType}" + value.appendValues(materialValue) + break + assert foundValue, &"Uniform '{uniform.name}' not found in scene shaderGlobals or materials" + assert (uniform.arrayCount == 0 and value.len == 1) or value.len == uniform.arrayCount, &"Uniform '{uniform.name}' found has wrong length (shader declares {uniform.arrayCount} but shaderGlobals and materials only provide {value.len})" + let (pdata, size) = value.getRawData() + assert size == uniform.size, "During uniform update: gathered value has size {size} but uniform expects size {uniform.size}" + debug &" update uniform {uniform.name} with value: {value}" + # TODO: technically we would only need to update the uniform buffer of the current + # frameInFlight, but we don't track for which frame the shaderglobals are no longer dirty + # therefore we have to update the uniform values in all buffers, of all inFlightframes (usually 2) + for buffer in renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk]: + buffer.setData(pdata, size, offset) + offset += uniform.size + scene.clearDirtyShaderGlobals() + +proc render*(renderer: var Renderer, scene: Scene) = + assert scene in renderer.scenedata + + var + commandBufferResult = renderer.swapchain.nextFrame() + commandBuffer: VkCommandBuffer + + if not commandBufferResult.isSome: + let res = renderer.swapchain.recreate() + if res.isSome: + var oldSwapchain = renderer.swapchain + renderer.swapchain = res.get() + checkVkResult renderer.device.vk.vkDeviceWaitIdle() + oldSwapchain.destroy() + return + + commandBuffer = commandBufferResult.get() + commandBuffer.beginRenderCommands(renderer.renderPass, renderer.swapchain.currentFramebuffer()) + + debug "Scene buffers:" + for (location, buffer) in renderer.scenedata[scene].vertexBuffers.pairs: + debug " ", location, ": ", buffer + debug " Index buffer: ", renderer.scenedata[scene].indexBuffer + + for i in 0 ..< renderer.renderPass.subpasses.len: + for (materialType, shaderPipeline) in renderer.renderPass.subpasses[i].shaderPipelines: + if scene.usesMaterial(materialType): + debug &"Start shaderPipeline for '{materialType}'" + commandBuffer.vkCmdBindPipeline(renderer.renderPass.subpasses[i].pipelineBindPoint, shaderPipeline.vk) + commandBuffer.vkCmdBindDescriptorSets(renderer.renderPass.subpasses[i].pipelineBindPoint, shaderPipeline.layout, 0, 1, addr(renderer.scenedata[scene].descriptorSets[shaderPipeline.vk][renderer.swapchain.currentInFlight].vk), 0, nil) + for (drawable, mesh) in renderer.scenedata[scene].drawables.filterIt(it[1].visible and it[1].material.theType == materialType): + drawable.draw(commandBuffer, vertexBuffers=renderer.scenedata[scene].vertexBuffers, indexBuffer=renderer.scenedata[scene].indexBuffer, shaderPipeline.vk) + + if i < renderer.renderPass.subpasses.len - 1: + commandBuffer.vkCmdNextSubpass(VK_SUBPASS_CONTENTS_INLINE) + + commandBuffer.endRenderCommands() + + if not renderer.swapchain.swap(): + let res = renderer.swapchain.recreate() + if res.isSome: + var oldSwapchain = renderer.swapchain + renderer.swapchain = res.get() + checkVkResult renderer.device.vk.vkDeviceWaitIdle() + oldSwapchain.destroy() + +func framesRendered*(renderer: Renderer): uint64 = + renderer.swapchain.framesRendered + +func valid*(renderer: Renderer): bool = + renderer.device.vk.valid + +proc destroy*(renderer: var Renderer, scene: Scene) = + var scenedata = renderer.scenedata[scene] + + for buffer in scenedata.vertexBuffers.mvalues: + assert buffer.vk.valid + buffer.destroy() + if scenedata.indexBuffer.vk.valid: + assert scenedata.indexBuffer.vk.valid + scenedata.indexBuffer.destroy() + for pipelineUniforms in scenedata.uniformBuffers.mvalues: + for buffer in pipelineUniforms.mitems: + assert buffer.vk.valid + buffer.destroy() + for pipelineTextures in scenedata.textures.mvalues: + for textures in pipelineTextures.mvalues: + for texture in textures.mitems: + texture.destroy() + for descriptorPool in scenedata.descriptorPools.mvalues: + descriptorPool.destroy() + +proc destroy*(renderer: var Renderer) = + for scenedata in renderer.scenedata.mvalues: + for buffer in scenedata.vertexBuffers.mvalues: + assert buffer.vk.valid + buffer.destroy() + if scenedata.indexBuffer.vk.valid: + assert scenedata.indexBuffer.vk.valid + scenedata.indexBuffer.destroy() + for pipelineUniforms in scenedata.uniformBuffers.mvalues: + for buffer in pipelineUniforms.mitems: + assert buffer.vk.valid + buffer.destroy() + for pipelineTextures in scenedata.textures.mvalues: + for textures in pipelineTextures.mvalues: + for texture in textures.mitems: + texture.destroy() + for descriptorPool in scenedata.descriptorPools.mvalues: + descriptorPool.destroy() + renderer.emptyTexture.destroy() + renderer.renderPass.destroy() + renderer.swapchain.destroy() diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/resources.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/resources.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,149 @@ +import std/streams +import std/strutils +import std/strformat +import std/os +import std/unicode + +import ./core +import ./resources/image +import ./resources/audio +import ./resources/mesh +import ./resources/font +import ./mesh +import ./material + +export image +export audio +export mesh + +type + ResourceBundlingType = enum + Dir # Directories + Zip # Zip files + Exe # Embeded in executable + +const thebundletype = parseEnum[ResourceBundlingType](BUNDLETYPE.toLowerAscii().capitalizeAscii()) +var selectedMod* = "default" + +# resource loading + +when thebundletype == Dir: + + proc resourceRoot(): string = + joinPath(absolutePath(getAppDir()), RESOURCEROOT) + proc modRoot(): string = + joinPath(resourceRoot(), selectedMod) + + proc loadResource_intern(path: string): Stream = + let realpath = joinPath(modRoot(), path) + if not realpath.fileExists(): + raise newException(Exception, &"Resource {path} not found") + newFileStream(realpath, fmRead) + + proc modList_intern(): seq[string] = + for kind, file in walkDir(resourceRoot(), relative=true): + if kind == pcDir: + result.add file + + iterator walkResources_intern(): string = + for file in walkDirRec(modRoot(), relative=true): + yield file + +elif thebundletype == Zip: + + import zippy/ziparchives + + proc resourceRoot(): string = + joinPath(absolutePath(getAppDir()), RESOURCEROOT) + proc modRoot(): string = + joinPath(resourceRoot(), selectedMod) + + proc loadResource_intern(path: string): Stream = + if not path.fileExists(): + raise newException(Exception, &"Resource {path} not found") + let archive = openZipArchive(modRoot() & ".zip") + # read all here so we can close the stream + result = newStringStream(archive.extractFile(path)) + archive.close() + + proc modList_intern(): seq[string] = + for kind, file in walkDir(resourceRoot(), relative=true): + if kind == pcFile and file.endsWith(".zip"): + result.add file[0 ..< ^4] + + iterator walkResources_intern(): string = + let archive = openZipArchive(modRoot() & ".zip") + for i in archive.walkFiles: + if i[^1] != '/': + yield i + archive.close() + +elif thebundletype == Exe: + + import std/compilesettings + import std/tables + import std/sequtils + + proc loadResources(): Table[string, Table[string, string]] {.compileTime.} = + + let srcdir = joinPath(parentDir(querySetting(projectFull)), RESOURCEROOT) + for kind, moddir in walkDir(srcdir): + if kind == pcDir: + let modname = moddir.splitPath.tail + result[modname] = Table[string, string]() + for resourcefile in walkDirRec(moddir, relative=true): + # TODO: add Lempel–Ziv–Welch compression or something similar simple + result[modname][resourcefile] = staticRead(joinPath(moddir, resourcefile)) + const bundledResources = loadResources() + + proc loadResource_intern(path: string): Stream = + if not (path in bundledResources[selectedMod]): + raise newException(Exception, &"Resource {path} not found") + newStringStream(bundledResources[selectedMod][path]) + + proc modList_intern(): seq[string] = + result = bundledResources.keys().toSeq() + + iterator walkResources_intern(): string = + for i in bundledResources[selectedMod].keys: + yield i + +proc loadResource*(path: string): Stream = + loadResource_intern(path) + +proc loadImage*(path: string): Image = + if path.splitFile().ext.toLowerAscii == ".bmp": + loadResource_intern(path).readBMP() + elif path.splitFile().ext.toLowerAscii == ".png": + loadResource_intern(path).readPNG() + else: + raise newException(Exception, "Unsupported image file type: " & path) + +proc loadAudio*(path: string): Sound = + if path.splitFile().ext.toLowerAscii == ".au": + loadResource_intern(path).readAU() + elif path.splitFile().ext.toLowerAscii == ".ogg": + loadResource_intern(path).readVorbis() + else: + raise newException(Exception, "Unsupported audio file type: " & path) + +proc loadFont*(path: string, name="", color=newVec4f(1, 1, 1, 1), resolution=100'f32): Font = + var thename = name + if thename == "": + thename = path.splitFile().name + let defaultCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_=+[{]};:,<.>/? $!@#%^&*()\"'".toRunes() + loadResource_intern(path).readTrueType(name, defaultCharset, color, resolution) + +proc loadMeshes*(path: string, defaultMaterial: MaterialType): seq[MeshTree] = + loadResource_intern(path).readglTF(defaultMaterial) + +proc loadFirstMesh*(path: string, defaultMaterial: MaterialType): Mesh = + loadResource_intern(path).readglTF(defaultMaterial)[0].toSeq[0] + +proc modList*(): seq[string] = + modList_intern() + +iterator walkResources*(dir=""): string = + for i in walkResources_intern(): + if i.startsWith(dir): + yield i diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/resources/audio.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/resources/audio.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,93 @@ +import std/os +import std/streams +import std/strformat +import std/endians + +import ../core/audiotypes + +type + Encoding {.size: sizeof(uint32).} = enum + # Unspecified = 0 + # Uint8Ulaw = 1 + # Int8 = 2 + Int16 = 3 + # Int24 = 4 + # Int32 = 5 + # Float32 = 6 + # Float64 = 7 + + AuHeader = object + magicNumber: uint32 + dataOffset: uint32 + dataSize: uint32 + encoding: Encoding + sampleRate: uint32 + channels: uint32 + +proc readSample(stream: Stream, encoding: Encoding, channels: int): Sample = + result[0] = stream.readint16() + swapEndian16(addr result[0], addr result[0]) + + if channels == 2: + result[1] = stream.readint16() + swapEndian16(addr result[1], addr result[1]) + else: + result[1] = result[0] + +# https://en.wikipedia.org/wiki/Au_file_format +proc readAU*(stream: Stream): Sound = + var header: AuHeader + + for name, value in fieldPairs(header): + var bytes: array[4, uint8] + stream.read(bytes) + swap(bytes[0], bytes[3]) + swap(bytes[1], bytes[2]) + value = cast[typeof(value)](bytes) + + assert header.magicNumber == 0x2e736e64 + if header.sampleRate != AUDIO_SAMPLE_RATE: + raise newException(Exception, &"Only support sample rate of {AUDIO_SAMPLE_RATE} Hz but got {header.sampleRate} Hz, please resample (e.g. ffmpeg -i -ar {AUDIO_SAMPLE_RATE} )") + if not (header.channels in [1'u32, 2'u32]): + raise newException(Exception, "Only support mono and stereo audio at the moment (1 or 2 channels), but found " & $header.channels) + + var annotation: string + stream.read(annotation) + + result = new Sound + stream.setPosition(int(header.dataOffset)) + while not stream.atEnd(): + result[].add stream.readSample(header.encoding, int(header.channels)) + +{.compile: currentSourcePath.parentDir() & "/stb_vorbis.c" .} + +proc stb_vorbis_decode_memory(mem: pointer, len: cint, channels: ptr cint, sample_rate: ptr cint, output: ptr ptr cshort): cint {.importc.} +proc free(p: pointer) {.importc.} + +proc readVorbis*(stream: Stream): Sound = + var + data = stream.readAll() + channels: cint + sampleRate: cint + output: ptr cshort + + var nSamples = stb_vorbis_decode_memory(addr data[0], cint(data.len), addr channels, addr sampleRate, addr output) + + if nSamples < 0: + raise newException(Exception, &"Unable to read ogg/vorbis sound file, error code: {nSamples}") + if sampleRate != AUDIO_SAMPLE_RATE: + raise newException(Exception, &"Only support sample rate of {AUDIO_SAMPLE_RATE} Hz but got {sampleRate} Hz, please resample (e.g. ffmpeg -i -acodec libvorbis -ar {AUDIO_SAMPLE_RATE} )") + + result = new Sound + if channels == 2: + result[].setLen(int(nSamples)) + copyMem(addr result[][0], output, nSamples * sizeof(Sample)) + free(output) + elif channels == 1: + for i in 0 ..< nSamples: + let value = cast[ptr UncheckedArray[int16]](output)[i] + result[].add [value, value] + free(output) + else: + free(output) + raise newException(Exception, "Only support mono and stereo audio at the moment (1 or 2 channels), but found " & $channels) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/resources/font.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/resources/font.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,103 @@ +import std/tables +import std/math +import std/streams +import std/os +import std/unicode + +import ../core/vector +import ../core/imagetypes +import ../core/fonttypes + +{.emit: "#define STBTT_STATIC" .} +{.emit: "#define STB_TRUETYPE_IMPLEMENTATION" .} +{.emit: "#include \"" & currentSourcePath.parentDir() & "/stb_truetype.h\"" .} + +type + stbtt_fontinfo {.importc, incompleteStruct .} = object + +proc stbtt_InitFont(info: ptr stbtt_fontinfo, data: ptr char, offset: cint): cint {.importc, nodecl.} +proc stbtt_ScaleForPixelHeight(info: ptr stbtt_fontinfo, pixels: cfloat): cfloat {.importc, nodecl.} +proc stbtt_GetCodepointBitmap(info: ptr stbtt_fontinfo, scale_x: cfloat, scale_y: cfloat, codepoint: cint, width, height, xoff, yoff: ptr cint): cstring {.importc, nodecl.} +proc stbtt_GetCodepointHMetrics(info: ptr stbtt_fontinfo, codepoint: cint, advance, leftBearing: ptr cint) {.importc, nodecl.} +proc stbtt_GetCodepointKernAdvance(info: ptr stbtt_fontinfo, ch1, ch2: cint): cint {.importc, nodecl.} + +proc free(p: pointer) {.importc.} + +proc readTrueType*(stream: Stream, name: string, codePoints: seq[Rune], color: Vec4f, resolution: float32): Font = + var + indata = stream.readAll() + fontinfo: stbtt_fontinfo + if stbtt_InitFont(addr fontinfo, addr indata[0], 0) == 0: + raise newException(Exception, "An error occured while loading PNG file") + + result.resolution = resolution + result.fontscale = float32(stbtt_ScaleForPixelHeight(addr fontinfo, cfloat(resolution))) + var + offsetX = 0 + bitmaps: Table[Rune, (cstring, cint, cint)] + topOffsets: Table[Rune, int] + for codePoint in codePoints: + var + width, height: cint + offX, offY: cint + data = stbtt_GetCodepointBitmap( + addr fontinfo, + result.fontscale, result.fontscale, + cint(codePoint), + addr width, addr height, + addr offX, addr offY + ) + bitmaps[codePoint] = (data, width, height) + result.maxHeight = max(result.maxHeight, int(height)) + offsetX += width + 1 + topOffsets[codePoint] = offY + + result.name = name + result.fontAtlas = Texture( + name: name & "_texture", + image: newImage(offsetX, result.maxHeight + 1), + sampler: FONTSAMPLER_SOFT + ) + + offsetX = 0 + for codePoint in codePoints: + let + bitmap = bitmaps[codePoint][0] + width = bitmaps[codePoint][1] + height = bitmaps[codePoint][2] + + # bitmap data + for y in 0 ..< height: + for x in 0 ..< width: + let value = float32(bitmap[y * width + x]) + result.fontAtlas.image[x + offsetX, y] = [ + uint8(round(color.r * 255'f32)), + uint8(round(color.g * 255'f32)), + uint8(round(color.b * 255'f32)), + uint8(round(color.a * value)) + ] + + # horizontal spaces: + var advance, leftBearing: cint + stbtt_GetCodepointHMetrics(addr fontinfo, cint(codePoint), addr advance, addr leftBearing) + + result.glyphs[codePoint] = GlyphInfo( + dimension: newVec2f(float32(width), float32(height)), + uvs: [ + newVec2f(float32(offsetX) / float32(result.fontAtlas.image.width), int(height) / result.maxHeight), + newVec2f(float32(offsetX) / float32(result.fontAtlas.image.width), 0), + newVec2f(float32(offsetX + width) / float32(result.fontAtlas.image.width), 0), + newVec2f(float32(offsetX + width) / float32(result.fontAtlas.image.width), int(height) / result.maxHeight), + ], + topOffset: float32(topOffsets[codePoint]), + leftOffset: float32(leftBearing) * result.fontscale, + advance: float32(advance) * result.fontscale, + ) + offsetX += width + 1 + free(bitmap) + for codePointAfter in codePoints: + result.kerning[(codePoint, codePointAfter)] = float32(stbtt_GetCodepointKernAdvance( + addr fontinfo, + cint(codePoint), + cint(codePointAfter) + )) * result.fontscale diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/resources/image.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/resources/image.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,125 @@ +import os +import std/streams +import std/bitops + +import ../core/imagetypes + +const COMPRESSION_BI_RGB = 0'u32 +const COMPRESSION_BI_BITFIELDS = 3'u32 +const COMPRESSION_BI_ALPHABITFIELDS = 6'u32 +type + BitmapFileHeader = object + magicbytes: array[2, char] + filesize: uint32 + reserved1: uint16 + reserved2: uint16 + dataStart: uint32 + DIBHeader = object + headersize: uint32 + width: int32 + height: int32 + colorPlanes: uint16 + bitsPerPixel: uint16 + compression: uint32 + imageDataSize: uint32 # unused + resolutionX: int32 # unused + resolutionY: int32 # unused + nColors: uint32 # unused + nImportantColors: uint32 # unused + bitMaskRed: uint32 + bitMaskGreen: uint32 + bitMaskBlue: uint32 + bitMaskAlpha: uint32 + colorSpace: array[4, char] # not used yet + colorSpaceEndpoints: array[36, uint8] # unused + gammaRed: uint32 # not used yet + gammaGreen: uint32 # not used yet + gammaBlue: uint32 # not used yet + +proc readBMP*(stream: Stream): Image = + var + bitmapFileHeader: BitmapFileHeader + dibHeader: DIBHeader + + for name, value in fieldPairs(bitmapFileHeader): + stream.read(value) + if bitmapFileHeader.magicbytes != ['B', 'M']: + raise newException(Exception, "Cannot open image, invalid magic bytes (is this really a BMP bitmap?)") + for name, value in fieldPairs(dibHeader): + + when name in ["bitMaskRed", "bitMaskGreen", "bitMaskBlue"]: + if dibHeader.compression in [COMPRESSION_BI_BITFIELDS, COMPRESSION_BI_ALPHABITFIELDS]: + stream.read(value) + elif name == "bitMaskAlpha": + if dibHeader.compression == COMPRESSION_BI_ALPHABITFIELDS: + stream.read(value) + else: + stream.read(value) + + when name == "headersize": + if value != 124: + raise newException(Exception, "Cannot open image, only BITMAPV5 supported") + elif name == "colorPlanes": + assert value == 1 + elif name == "bitsPerPixel": + if not (value in [24'u16, 32'u16]): + raise newException(Exception, "Cannot open image, only depth of 24 and 32 supported") + elif name == "compression": + if not (value in [0'u32, 3'u32]): + raise newException(Exception, "Cannot open image, only BI_RGB and BI_BITFIELDS are supported compressions") + elif name == "colorSpace": + swap(value[0], value[3]) + swap(value[1], value[2]) + stream.setPosition(int(bitmapFileHeader.dataStart)) + var + padding = ((int32(dibHeader.bitsPerPixel div 8)) * dibHeader.width) mod 4 + data = newSeq[Pixel](dibHeader.width * abs(dibHeader.height)) + if padding > 0: + padding = 4 - padding + for row in 0 ..< abs(dibHeader.height): + for col in 0 ..< dibHeader.width: + + var pixel: Pixel = [0'u8, 0'u8, 0'u8, 255'u8] + # if we got channeld bitmasks + if dibHeader.compression in [COMPRESSION_BI_BITFIELDS, COMPRESSION_BI_ALPHABITFIELDS]: + var value = stream.readUint32() + pixel[0] = uint8((value and dibHeader.bitMaskRed) shr dibHeader.bitMaskRed.countTrailingZeroBits) + pixel[1] = uint8((value and dibHeader.bitMaskGreen) shr dibHeader.bitMaskGreen.countTrailingZeroBits) + pixel[2] = uint8((value and dibHeader.bitMaskBlue) shr dibHeader.bitMaskBlue.countTrailingZeroBits) + if dibHeader.compression == COMPRESSION_BI_ALPHABITFIELDS: + pixel[3] = uint8((value and dibHeader.bitMaskAlpha) shr dibHeader.bitMaskAlpha.countTrailingZeroBits) + # if we got plain RGB(A), using little endian + elif dibHeader.compression == COMPRESSION_BI_RGB: + let nChannels = int(dibHeader.bitsPerPixel) div 8 + for i in 1 .. nChannels: + stream.read(pixel[nChannels - i]) + else: + raise newException(Exception, "Cannot open image, only BI_RGB and BI_BITFIELDS are supported compressions") + + # determine whether we read top-to-bottom or bottom-to-top + var row_mult: int = (if dibHeader.height < 0: row else: dibHeader.height - row - 1) + data[row_mult * dibHeader.width + col]= pixel + stream.setPosition(stream.getPosition() + padding) + + result = newImage(width=dibHeader.width, height=abs(dibHeader.height), imagedata=data) + +{.compile: currentSourcePath.parentDir() & "/lodepng.c" .} + +proc lodepng_decode32(out_data: ptr cstring, w: ptr cuint, h: ptr cuint, in_data: cstring, insize: csize_t): cuint {.importc.} +proc free(p: pointer) {.importc.} # for some reason the lodepng pointer can only properly be freed with the native free + +proc readPNG*(stream: Stream): Image = + let indata = stream.readAll() + var w, h: cuint + var data: cstring + + if lodepng_decode32(out_data=addr data, w=addr w, h=addr h, in_data=cstring(indata), insize=csize_t(indata.len)) != 0: + raise newException(Exception, "An error occured while loading PNG file") + + let imagesize = w * h * 4 + var imagedata = newSeq[Pixel](w * h) + copyMem(addr imagedata[0], data, imagesize) + + free(data) + + result = newImage(width=int(w), height=int(h), imagedata=imagedata) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/resources/lodepng.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/resources/lodepng.c Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,6991 @@ +/* +LodePNG version 20230410 + +Copyright (c) 2005-2023 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +/* +The manual and changelog are in the header file "lodepng.h" +Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C. +*/ + +#include "lodepng.h" + +#ifdef LODEPNG_COMPILE_DISK +#include /* LONG_MAX */ +#include /* file handling */ +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ALLOCATORS +#include /* allocations */ +#endif /* LODEPNG_COMPILE_ALLOCATORS */ + +#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/ +#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/ +#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ +#endif /*_MSC_VER */ + +const char* LODEPNG_VERSION_STRING = "20230410"; + +/* +This source file is divided into the following large parts. The code sections +with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way. +-Tools for C and common code for PNG and Zlib +-C Code for Zlib (huffman, deflate, ...) +-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...) +-The C++ wrapper around all of the above +*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // Tools for C, and common code for PNG and Zlib. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*The malloc, realloc and free functions defined here with "lodepng_" in front +of the name, so that you can easily change them to others related to your +platform if needed. Everything else in the code calls these. Pass +-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out +#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and +define them in your own project's source files without needing to change +lodepng source code. Don't forget to remove "static" if you copypaste them +from here.*/ + +#ifdef LODEPNG_COMPILE_ALLOCATORS +static void* lodepng_malloc(size_t size) { +#ifdef LODEPNG_MAX_ALLOC + if(size > LODEPNG_MAX_ALLOC) return 0; +#endif + return malloc(size); +} + +/* NOTE: when realloc returns NULL, it leaves the original memory untouched */ +static void* lodepng_realloc(void* ptr, size_t new_size) { +#ifdef LODEPNG_MAX_ALLOC + if(new_size > LODEPNG_MAX_ALLOC) return 0; +#endif + return realloc(ptr, new_size); +} + +static void lodepng_free(void* ptr) { + free(ptr); +} +#else /*LODEPNG_COMPILE_ALLOCATORS*/ +/* TODO: support giving additional void* payload to the custom allocators */ +void* lodepng_malloc(size_t size); +void* lodepng_realloc(void* ptr, size_t new_size); +void lodepng_free(void* ptr); +#endif /*LODEPNG_COMPILE_ALLOCATORS*/ + +/* convince the compiler to inline a function, for use when this measurably improves performance */ +/* inline is not available in C90, but use it when supported by the compiler */ +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined(__cplusplus) && (__cplusplus >= 199711L)) +#define LODEPNG_INLINE inline +#else +#define LODEPNG_INLINE /* not available */ +#endif + +/* restrict is not available in C90, but use it when supported by the compiler */ +#if (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) ||\ + (defined(_MSC_VER) && (_MSC_VER >= 1400)) || \ + (defined(__WATCOMC__) && (__WATCOMC__ >= 1250) && !defined(__cplusplus)) +#define LODEPNG_RESTRICT __restrict +#else +#define LODEPNG_RESTRICT /* not available */ +#endif + +/* Replacements for C library functions such as memcpy and strlen, to support platforms +where a full C library is not available. The compiler can recognize them and compile +to something as fast. */ + +static void lodepng_memcpy(void* LODEPNG_RESTRICT dst, + const void* LODEPNG_RESTRICT src, size_t size) { + size_t i; + for(i = 0; i < size; i++) ((char*)dst)[i] = ((const char*)src)[i]; +} + +static void lodepng_memset(void* LODEPNG_RESTRICT dst, + int value, size_t num) { + size_t i; + for(i = 0; i < num; i++) ((char*)dst)[i] = (char)value; +} + +/* does not check memory out of bounds, do not use on untrusted data */ +static size_t lodepng_strlen(const char* a) { + const char* orig = a; + /* avoid warning about unused function in case of disabled COMPILE... macros */ + (void)(&lodepng_strlen); + while(*a) a++; + return (size_t)(a - orig); +} + +#define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER) +/* Safely check if adding two integers will overflow (no undefined +behavior, compiler removing the code, etc...) and output result. */ +static int lodepng_addofl(size_t a, size_t b, size_t* result) { + *result = a + b; /* Unsigned addition is well defined and safe in C90 */ + return *result < a; +} +#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)*/ + +#ifdef LODEPNG_COMPILE_DECODER +/* Safely check if multiplying two integers will overflow (no undefined +behavior, compiler removing the code, etc...) and output result. */ +static int lodepng_mulofl(size_t a, size_t b, size_t* result) { + *result = a * b; /* Unsigned multiplication is well defined and safe in C90 */ + return (a != 0 && *result / a != b); +} + +#ifdef LODEPNG_COMPILE_ZLIB +/* Safely check if a + b > c, even if overflow could happen. */ +static int lodepng_gtofl(size_t a, size_t b, size_t c) { + size_t d; + if(lodepng_addofl(a, b, &d)) return 1; + return d > c; +} +#endif /*LODEPNG_COMPILE_ZLIB*/ +#endif /*LODEPNG_COMPILE_DECODER*/ + + +/* +Often in case of an error a value is assigned to a variable and then it breaks +out of a loop (to go to the cleanup phase of a function). This macro does that. +It makes the error handling code shorter and more readable. + +Example: if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83); +*/ +#define CERROR_BREAK(errorvar, code){\ + errorvar = code;\ + break;\ +} + +/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/ +#define ERROR_BREAK(code) CERROR_BREAK(error, code) + +/*Set error var to the error code, and return it.*/ +#define CERROR_RETURN_ERROR(errorvar, code){\ + errorvar = code;\ + return code;\ +} + +/*Try the code, if it returns error, also return the error.*/ +#define CERROR_TRY_RETURN(call){\ + unsigned error = call;\ + if(error) return error;\ +} + +/*Set error var to the error code, and return from the void function.*/ +#define CERROR_RETURN(errorvar, code){\ + errorvar = code;\ + return;\ +} + +/* +About uivector, ucvector and string: +-All of them wrap dynamic arrays or text strings in a similar way. +-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. +-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. +-They're not used in the interface, only internally in this file as static functions. +-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor. +*/ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_ENCODER +/*dynamic vector of unsigned ints*/ +typedef struct uivector { + unsigned* data; + size_t size; /*size in number of unsigned longs*/ + size_t allocsize; /*allocated size in bytes*/ +} uivector; + +static void uivector_cleanup(void* p) { + ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; + lodepng_free(((uivector*)p)->data); + ((uivector*)p)->data = NULL; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_resize(uivector* p, size_t size) { + size_t allocsize = size * sizeof(unsigned); + if(allocsize > p->allocsize) { + size_t newsize = allocsize + (p->allocsize >> 1u); + void* data = lodepng_realloc(p->data, newsize); + if(data) { + p->allocsize = newsize; + p->data = (unsigned*)data; + } + else return 0; /*error: not enough memory*/ + } + p->size = size; + return 1; /*success*/ +} + +static void uivector_init(uivector* p) { + p->data = NULL; + p->size = p->allocsize = 0; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_push_back(uivector* p, unsigned c) { + if(!uivector_resize(p, p->size + 1)) return 0; + p->data[p->size - 1] = c; + return 1; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_ZLIB*/ + +/* /////////////////////////////////////////////////////////////////////////// */ + +/*dynamic vector of unsigned chars*/ +typedef struct ucvector { + unsigned char* data; + size_t size; /*used size*/ + size_t allocsize; /*allocated size*/ +} ucvector; + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_reserve(ucvector* p, size_t size) { + if(size > p->allocsize) { + size_t newsize = size + (p->allocsize >> 1u); + void* data = lodepng_realloc(p->data, newsize); + if(data) { + p->allocsize = newsize; + p->data = (unsigned char*)data; + } + else return 0; /*error: not enough memory*/ + } + return 1; /*success*/ +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_resize(ucvector* p, size_t size) { + p->size = size; + return ucvector_reserve(p, size); +} + +static ucvector ucvector_init(unsigned char* buffer, size_t size) { + ucvector v; + v.data = buffer; + v.allocsize = v.size = size; + return v; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_PNG +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +/*free string pointer and set it to NULL*/ +static void string_cleanup(char** out) { + lodepng_free(*out); + *out = NULL; +} + +/*also appends null termination character*/ +static char* alloc_string_sized(const char* in, size_t insize) { + char* out = (char*)lodepng_malloc(insize + 1); + if(out) { + lodepng_memcpy(out, in, insize); + out[insize] = 0; + } + return out; +} + +/* dynamically allocates a new string with a copy of the null terminated input text */ +static char* alloc_string(const char* in) { + return alloc_string_sized(in, lodepng_strlen(in)); +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +/* ////////////////////////////////////////////////////////////////////////// */ + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG) +static unsigned lodepng_read32bitInt(const unsigned char* buffer) { + return (((unsigned)buffer[0] << 24u) | ((unsigned)buffer[1] << 16u) | + ((unsigned)buffer[2] << 8u) | (unsigned)buffer[3]); +} +#endif /*defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG)*/ + +#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) +/*buffer must have at least 4 allocated bytes available*/ +static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) { + buffer[0] = (unsigned char)((value >> 24) & 0xff); + buffer[1] = (unsigned char)((value >> 16) & 0xff); + buffer[2] = (unsigned char)((value >> 8) & 0xff); + buffer[3] = (unsigned char)((value ) & 0xff); +} +#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / File IO / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_DISK + +/* returns negative value on error. This should be pure C compatible, so no fstat. */ +static long lodepng_filesize(const char* filename) { + FILE* file; + long size; + file = fopen(filename, "rb"); + if(!file) return -1; + + if(fseek(file, 0, SEEK_END) != 0) { + fclose(file); + return -1; + } + + size = ftell(file); + /* It may give LONG_MAX as directory size, this is invalid for us. */ + if(size == LONG_MAX) size = -1; + + fclose(file); + return size; +} + +/* load file into buffer that already has the correct allocated size. Returns error code.*/ +static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) { + FILE* file; + size_t readsize; + file = fopen(filename, "rb"); + if(!file) return 78; + + readsize = fread(out, 1, size, file); + fclose(file); + + if(readsize != size) return 78; + return 0; +} + +unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) { + long size = lodepng_filesize(filename); + if(size < 0) return 78; + *outsize = (size_t)size; + + *out = (unsigned char*)lodepng_malloc((size_t)size); + if(!(*out) && size > 0) return 83; /*the above malloc failed*/ + + return lodepng_buffer_file(*out, (size_t)size, filename); +} + +/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ +unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) { + FILE* file; + file = fopen(filename, "wb" ); + if(!file) return 79; + fwrite(buffer, 1, buffersize, file); + fclose(file); + return 0; +} + +#endif /*LODEPNG_COMPILE_DISK*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // End of common code and tools. Begin of Zlib related code. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_ENCODER + +typedef struct { + ucvector* data; + unsigned char bp; /*ok to overflow, indicates bit pos inside byte*/ +} LodePNGBitWriter; + +static void LodePNGBitWriter_init(LodePNGBitWriter* writer, ucvector* data) { + writer->data = data; + writer->bp = 0; +} + +/*TODO: this ignores potential out of memory errors*/ +#define WRITEBIT(writer, bit){\ + /* append new byte */\ + if(((writer->bp) & 7u) == 0) {\ + if(!ucvector_resize(writer->data, writer->data->size + 1)) return;\ + writer->data->data[writer->data->size - 1] = 0;\ + }\ + (writer->data->data[writer->data->size - 1]) |= (bit << ((writer->bp) & 7u));\ + ++writer->bp;\ +} + +/* LSB of value is written first, and LSB of bytes is used first */ +static void writeBits(LodePNGBitWriter* writer, unsigned value, size_t nbits) { + if(nbits == 1) { /* compiler should statically compile this case if nbits == 1 */ + WRITEBIT(writer, value); + } else { + /* TODO: increase output size only once here rather than in each WRITEBIT */ + size_t i; + for(i = 0; i != nbits; ++i) { + WRITEBIT(writer, (unsigned char)((value >> i) & 1)); + } + } +} + +/* This one is to use for adding huffman symbol, the value bits are written MSB first */ +static void writeBitsReversed(LodePNGBitWriter* writer, unsigned value, size_t nbits) { + size_t i; + for(i = 0; i != nbits; ++i) { + /* TODO: increase output size only once here rather than in each WRITEBIT */ + WRITEBIT(writer, (unsigned char)((value >> (nbits - 1u - i)) & 1u)); + } +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +typedef struct { + const unsigned char* data; + size_t size; /*size of data in bytes*/ + size_t bitsize; /*size of data in bits, end of valid bp values, should be 8*size*/ + size_t bp; + unsigned buffer; /*buffer for reading bits. NOTE: 'unsigned' must support at least 32 bits*/ +} LodePNGBitReader; + +/* data size argument is in bytes. Returns error if size too large causing overflow */ +static unsigned LodePNGBitReader_init(LodePNGBitReader* reader, const unsigned char* data, size_t size) { + size_t temp; + reader->data = data; + reader->size = size; + /* size in bits, return error if overflow (if size_t is 32 bit this supports up to 500MB) */ + if(lodepng_mulofl(size, 8u, &reader->bitsize)) return 105; + /*ensure incremented bp can be compared to bitsize without overflow even when it would be incremented 32 too much and + trying to ensure 32 more bits*/ + if(lodepng_addofl(reader->bitsize, 64u, &temp)) return 105; + reader->bp = 0; + reader->buffer = 0; + return 0; /*ok*/ +} + +/* +ensureBits functions: +Ensures the reader can at least read nbits bits in one or more readBits calls, +safely even if not enough bits are available. +The nbits parameter is unused but is given for documentation purposes, error +checking for amount of bits must be done beforehand. +*/ + +/*See ensureBits documentation above. This one ensures up to 9 bits */ +static LODEPNG_INLINE void ensureBits9(LodePNGBitReader* reader, size_t nbits) { + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 1u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u); + reader->buffer >>= (reader->bp & 7u); + } else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer = reader->data[start + 0]; + reader->buffer >>= (reader->bp & 7u); + } + (void)nbits; +} + +/*See ensureBits documentation above. This one ensures up to 17 bits */ +static LODEPNG_INLINE void ensureBits17(LodePNGBitReader* reader, size_t nbits) { + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 2u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | + ((unsigned)reader->data[start + 2] << 16u); + reader->buffer >>= (reader->bp & 7u); + } else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer |= reader->data[start + 0]; + if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); + reader->buffer >>= (reader->bp & 7u); + } + (void)nbits; +} + +/*See ensureBits documentation above. This one ensures up to 25 bits */ +static LODEPNG_INLINE void ensureBits25(LodePNGBitReader* reader, size_t nbits) { + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 3u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | + ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u); + reader->buffer >>= (reader->bp & 7u); + } else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer |= reader->data[start + 0]; + if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); + if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u); + reader->buffer >>= (reader->bp & 7u); + } + (void)nbits; +} + +/*See ensureBits documentation above. This one ensures up to 32 bits */ +static LODEPNG_INLINE void ensureBits32(LodePNGBitReader* reader, size_t nbits) { + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 4u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | + ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u); + reader->buffer >>= (reader->bp & 7u); + reader->buffer |= (((unsigned)reader->data[start + 4] << 24u) << (8u - (reader->bp & 7u))); + } else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer |= reader->data[start + 0]; + if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); + if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u); + if(start + 3u < size) reader->buffer |= ((unsigned)reader->data[start + 3] << 24u); + reader->buffer >>= (reader->bp & 7u); + } + (void)nbits; +} + +/* Get bits without advancing the bit pointer. Must have enough bits available with ensureBits. Max nbits is 31. */ +static LODEPNG_INLINE unsigned peekBits(LodePNGBitReader* reader, size_t nbits) { + /* The shift allows nbits to be only up to 31. */ + return reader->buffer & ((1u << nbits) - 1u); +} + +/* Must have enough bits available with ensureBits */ +static LODEPNG_INLINE void advanceBits(LodePNGBitReader* reader, size_t nbits) { + reader->buffer >>= nbits; + reader->bp += nbits; +} + +/* Must have enough bits available with ensureBits */ +static LODEPNG_INLINE unsigned readBits(LodePNGBitReader* reader, size_t nbits) { + unsigned result = peekBits(reader, nbits); + advanceBits(reader, nbits); + return result; +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +static unsigned reverseBits(unsigned bits, unsigned num) { + /*TODO: implement faster lookup table based version when needed*/ + unsigned i, result = 0; + for(i = 0; i < num; i++) result |= ((bits >> (num - i - 1u)) & 1u) << i; + return result; +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Deflate - Huffman / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#define FIRST_LENGTH_CODE_INDEX 257 +#define LAST_LENGTH_CODE_INDEX 285 +/*256 literals, the end code, some length codes, and 2 unused codes*/ +#define NUM_DEFLATE_CODE_SYMBOLS 288 +/*the distance codes have their own symbols, 30 used, 2 unused*/ +#define NUM_DISTANCE_SYMBOLS 32 +/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ +#define NUM_CODE_LENGTH_CODES 19 + +/*the base lengths represented by codes 257-285*/ +static const unsigned LENGTHBASE[29] + = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, + 67, 83, 99, 115, 131, 163, 195, 227, 258}; + +/*the extra bits used by codes 257-285 (added to base length)*/ +static const unsigned LENGTHEXTRA[29] + = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, 0}; + +/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ +static const unsigned DISTANCEBASE[30] + = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, + 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; + +/*the extra bits of backwards distances (added to base)*/ +static const unsigned DISTANCEEXTRA[30] + = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; + +/*the order in which "code length alphabet code lengths" are stored as specified by deflate, out of this the huffman +tree of the dynamic huffman tree lengths is generated*/ +static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES] + = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* ////////////////////////////////////////////////////////////////////////// */ + +/* +Huffman tree struct, containing multiple representations of the tree +*/ +typedef struct HuffmanTree { + unsigned* codes; /*the huffman codes (bit patterns representing the symbols)*/ + unsigned* lengths; /*the lengths of the huffman codes*/ + unsigned maxbitlen; /*maximum number of bits a single code can get*/ + unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ + /* for reading only */ + unsigned char* table_len; /*length of symbol from lookup table, or max length if secondary lookup needed*/ + unsigned short* table_value; /*value of symbol from lookup table, or pointer to secondary table if needed*/ +} HuffmanTree; + +static void HuffmanTree_init(HuffmanTree* tree) { + tree->codes = 0; + tree->lengths = 0; + tree->table_len = 0; + tree->table_value = 0; +} + +static void HuffmanTree_cleanup(HuffmanTree* tree) { + lodepng_free(tree->codes); + lodepng_free(tree->lengths); + lodepng_free(tree->table_len); + lodepng_free(tree->table_value); +} + +/* amount of bits for first huffman table lookup (aka root bits), see HuffmanTree_makeTable and huffmanDecodeSymbol.*/ +/* values 8u and 9u work the fastest */ +#define FIRSTBITS 9u + +/* a symbol value too big to represent any valid symbol, to indicate reading disallowed huffman bits combination, +which is possible in case of only 0 or 1 present symbols. */ +#define INVALIDSYMBOL 65535u + +/* make table for huffman decoding */ +static unsigned HuffmanTree_makeTable(HuffmanTree* tree) { + static const unsigned headsize = 1u << FIRSTBITS; /*size of the first table*/ + static const unsigned mask = (1u << FIRSTBITS) /*headsize*/ - 1u; + size_t i, numpresent, pointer, size; /*total table size*/ + unsigned* maxlens = (unsigned*)lodepng_malloc(headsize * sizeof(unsigned)); + if(!maxlens) return 83; /*alloc fail*/ + + /* compute maxlens: max total bit length of symbols sharing prefix in the first table*/ + lodepng_memset(maxlens, 0, headsize * sizeof(*maxlens)); + for(i = 0; i < tree->numcodes; i++) { + unsigned symbol = tree->codes[i]; + unsigned l = tree->lengths[i]; + unsigned index; + if(l <= FIRSTBITS) continue; /*symbols that fit in first table don't increase secondary table size*/ + /*get the FIRSTBITS MSBs, the MSBs of the symbol are encoded first. See later comment about the reversing*/ + index = reverseBits(symbol >> (l - FIRSTBITS), FIRSTBITS); + maxlens[index] = LODEPNG_MAX(maxlens[index], l); + } + /* compute total table size: size of first table plus all secondary tables for symbols longer than FIRSTBITS */ + size = headsize; + for(i = 0; i < headsize; ++i) { + unsigned l = maxlens[i]; + if(l > FIRSTBITS) size += (1u << (l - FIRSTBITS)); + } + tree->table_len = (unsigned char*)lodepng_malloc(size * sizeof(*tree->table_len)); + tree->table_value = (unsigned short*)lodepng_malloc(size * sizeof(*tree->table_value)); + if(!tree->table_len || !tree->table_value) { + lodepng_free(maxlens); + /* freeing tree->table values is done at a higher scope */ + return 83; /*alloc fail*/ + } + /*initialize with an invalid length to indicate unused entries*/ + for(i = 0; i < size; ++i) tree->table_len[i] = 16; + + /*fill in the first table for long symbols: max prefix size and pointer to secondary tables*/ + pointer = headsize; + for(i = 0; i < headsize; ++i) { + unsigned l = maxlens[i]; + if(l <= FIRSTBITS) continue; + tree->table_len[i] = l; + tree->table_value[i] = pointer; + pointer += (1u << (l - FIRSTBITS)); + } + lodepng_free(maxlens); + + /*fill in the first table for short symbols, or secondary table for long symbols*/ + numpresent = 0; + for(i = 0; i < tree->numcodes; ++i) { + unsigned l = tree->lengths[i]; + unsigned symbol, reverse; + if(l == 0) continue; + symbol = tree->codes[i]; /*the huffman bit pattern. i itself is the value.*/ + /*reverse bits, because the huffman bits are given in MSB first order but the bit reader reads LSB first*/ + reverse = reverseBits(symbol, l); + numpresent++; + + if(l <= FIRSTBITS) { + /*short symbol, fully in first table, replicated num times if l < FIRSTBITS*/ + unsigned num = 1u << (FIRSTBITS - l); + unsigned j; + for(j = 0; j < num; ++j) { + /*bit reader will read the l bits of symbol first, the remaining FIRSTBITS - l bits go to the MSB's*/ + unsigned index = reverse | (j << l); + if(tree->table_len[index] != 16) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ + tree->table_len[index] = l; + tree->table_value[index] = i; + } + } else { + /*long symbol, shares prefix with other long symbols in first lookup table, needs second lookup*/ + /*the FIRSTBITS MSBs of the symbol are the first table index*/ + unsigned index = reverse & mask; + unsigned maxlen = tree->table_len[index]; + /*log2 of secondary table length, should be >= l - FIRSTBITS*/ + unsigned tablelen = maxlen - FIRSTBITS; + unsigned start = tree->table_value[index]; /*starting index in secondary table*/ + unsigned num = 1u << (tablelen - (l - FIRSTBITS)); /*amount of entries of this symbol in secondary table*/ + unsigned j; + if(maxlen < l) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ + for(j = 0; j < num; ++j) { + unsigned reverse2 = reverse >> FIRSTBITS; /* l - FIRSTBITS bits */ + unsigned index2 = start + (reverse2 | (j << (l - FIRSTBITS))); + tree->table_len[index2] = l; + tree->table_value[index2] = i; + } + } + } + + if(numpresent < 2) { + /* In case of exactly 1 symbol, in theory the huffman symbol needs 0 bits, + but deflate uses 1 bit instead. In case of 0 symbols, no symbols can + appear at all, but such huffman tree could still exist (e.g. if distance + codes are never used). In both cases, not all symbols of the table will be + filled in. Fill them in with an invalid symbol value so returning them from + huffmanDecodeSymbol will cause error. */ + for(i = 0; i < size; ++i) { + if(tree->table_len[i] == 16) { + /* As length, use a value smaller than FIRSTBITS for the head table, + and a value larger than FIRSTBITS for the secondary table, to ensure + valid behavior for advanceBits when reading this symbol. */ + tree->table_len[i] = (i < headsize) ? 1 : (FIRSTBITS + 1); + tree->table_value[i] = INVALIDSYMBOL; + } + } + } else { + /* A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. + If that is not the case (due to too long length codes), the table will not + have been fully used, and this is an error (not all bit combinations can be + decoded): an oversubscribed huffman tree, indicated by error 55. */ + for(i = 0; i < size; ++i) { + if(tree->table_len[i] == 16) return 55; + } + } + + return 0; +} + +/* +Second step for the ...makeFromLengths and ...makeFromFrequencies functions. +numcodes, lengths and maxbitlen must already be filled in correctly. return +value is error. +*/ +static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) { + unsigned* blcount; + unsigned* nextcode; + unsigned error = 0; + unsigned bits, n; + + tree->codes = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned)); + blcount = (unsigned*)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned)); + nextcode = (unsigned*)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned)); + if(!tree->codes || !blcount || !nextcode) error = 83; /*alloc fail*/ + + if(!error) { + for(n = 0; n != tree->maxbitlen + 1; n++) blcount[n] = nextcode[n] = 0; + /*step 1: count number of instances of each code length*/ + for(bits = 0; bits != tree->numcodes; ++bits) ++blcount[tree->lengths[bits]]; + /*step 2: generate the nextcode values*/ + for(bits = 1; bits <= tree->maxbitlen; ++bits) { + nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1u; + } + /*step 3: generate all the codes*/ + for(n = 0; n != tree->numcodes; ++n) { + if(tree->lengths[n] != 0) { + tree->codes[n] = nextcode[tree->lengths[n]]++; + /*remove superfluous bits from the code*/ + tree->codes[n] &= ((1u << tree->lengths[n]) - 1u); + } + } + } + + lodepng_free(blcount); + lodepng_free(nextcode); + + if(!error) error = HuffmanTree_makeTable(tree); + return error; +} + +/* +given the code lengths (as stored in the PNG file), generate the tree as defined +by Deflate. maxbitlen is the maximum bits that a code in the tree can have. +return value is error. +*/ +static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, + size_t numcodes, unsigned maxbitlen) { + unsigned i; + tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); + if(!tree->lengths) return 83; /*alloc fail*/ + for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i]; + tree->numcodes = (unsigned)numcodes; /*number of symbols*/ + tree->maxbitlen = maxbitlen; + return HuffmanTree_makeFromLengths2(tree); +} + +#ifdef LODEPNG_COMPILE_ENCODER + +/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding", +Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/ + +/*chain node for boundary package merge*/ +typedef struct BPMNode { + int weight; /*the sum of all weights in this chain*/ + unsigned index; /*index of this leaf node (called "count" in the paper)*/ + struct BPMNode* tail; /*the next nodes in this chain (null if last)*/ + int in_use; +} BPMNode; + +/*lists of chains*/ +typedef struct BPMLists { + /*memory pool*/ + unsigned memsize; + BPMNode* memory; + unsigned numfree; + unsigned nextfree; + BPMNode** freelist; + /*two heads of lookahead chains per list*/ + unsigned listsize; + BPMNode** chains0; + BPMNode** chains1; +} BPMLists; + +/*creates a new chain node with the given parameters, from the memory in the lists */ +static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) { + unsigned i; + BPMNode* result; + + /*memory full, so garbage collect*/ + if(lists->nextfree >= lists->numfree) { + /*mark only those that are in use*/ + for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0; + for(i = 0; i != lists->listsize; ++i) { + BPMNode* node; + for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1; + for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1; + } + /*collect those that are free*/ + lists->numfree = 0; + for(i = 0; i != lists->memsize; ++i) { + if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i]; + } + lists->nextfree = 0; + } + + result = lists->freelist[lists->nextfree++]; + result->weight = weight; + result->index = index; + result->tail = tail; + return result; +} + +/*sort the leaves with stable mergesort*/ +static void bpmnode_sort(BPMNode* leaves, size_t num) { + BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num); + size_t width, counter = 0; + for(width = 1; width < num; width *= 2) { + BPMNode* a = (counter & 1) ? mem : leaves; + BPMNode* b = (counter & 1) ? leaves : mem; + size_t p; + for(p = 0; p < num; p += 2 * width) { + size_t q = (p + width > num) ? num : (p + width); + size_t r = (p + 2 * width > num) ? num : (p + 2 * width); + size_t i = p, j = q, k; + for(k = p; k < r; k++) { + if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++]; + else b[k] = a[j++]; + } + } + counter++; + } + if(counter & 1) lodepng_memcpy(leaves, mem, sizeof(*leaves) * num); + lodepng_free(mem); +} + +/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/ +static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) { + unsigned lastindex = lists->chains1[c]->index; + + if(c == 0) { + if(lastindex >= numpresent) return; + lists->chains0[c] = lists->chains1[c]; + lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0); + } else { + /*sum of the weights of the head nodes of the previous lookahead chains.*/ + int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight; + lists->chains0[c] = lists->chains1[c]; + if(lastindex < numpresent && sum > leaves[lastindex].weight) { + lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail); + return; + } + lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]); + /*in the end we are only interested in the chain of the last list, so no + need to recurse if we're at the last one (this gives measurable speedup)*/ + if(num + 1 < (int)(2 * numpresent - 2)) { + boundaryPM(lists, leaves, numpresent, c - 1, num); + boundaryPM(lists, leaves, numpresent, c - 1, num); + } + } +} + +unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, + size_t numcodes, unsigned maxbitlen) { + unsigned error = 0; + unsigned i; + size_t numpresent = 0; /*number of symbols with non-zero frequency*/ + BPMNode* leaves; /*the symbols, only those with > 0 frequency*/ + + if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ + if((1u << maxbitlen) < (unsigned)numcodes) return 80; /*error: represent all symbols*/ + + leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves)); + if(!leaves) return 83; /*alloc fail*/ + + for(i = 0; i != numcodes; ++i) { + if(frequencies[i] > 0) { + leaves[numpresent].weight = (int)frequencies[i]; + leaves[numpresent].index = i; + ++numpresent; + } + } + + lodepng_memset(lengths, 0, numcodes * sizeof(*lengths)); + + /*ensure at least two present symbols. There should be at least one symbol + according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To + make these work as well ensure there are at least two symbols. The + Package-Merge code below also doesn't work correctly if there's only one + symbol, it'd give it the theoretical 0 bits but in practice zlib wants 1 bit*/ + if(numpresent == 0) { + lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/ + } else if(numpresent == 1) { + lengths[leaves[0].index] = 1; + lengths[leaves[0].index == 0 ? 1 : 0] = 1; + } else { + BPMLists lists; + BPMNode* node; + + bpmnode_sort(leaves, numpresent); + + lists.listsize = maxbitlen; + lists.memsize = 2 * maxbitlen * (maxbitlen + 1); + lists.nextfree = 0; + lists.numfree = lists.memsize; + lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory)); + lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*)); + lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); + lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); + if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/ + + if(!error) { + for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i]; + + bpmnode_create(&lists, leaves[0].weight, 1, 0); + bpmnode_create(&lists, leaves[1].weight, 2, 0); + + for(i = 0; i != lists.listsize; ++i) { + lists.chains0[i] = &lists.memory[0]; + lists.chains1[i] = &lists.memory[1]; + } + + /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/ + for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i); + + for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) { + for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index]; + } + } + + lodepng_free(lists.memory); + lodepng_free(lists.freelist); + lodepng_free(lists.chains0); + lodepng_free(lists.chains1); + } + + lodepng_free(leaves); + return error; +} + +/*Create the Huffman tree given the symbol frequencies*/ +static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies, + size_t mincodes, size_t numcodes, unsigned maxbitlen) { + unsigned error = 0; + while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/ + tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); + if(!tree->lengths) return 83; /*alloc fail*/ + tree->maxbitlen = maxbitlen; + tree->numcodes = (unsigned)numcodes; /*number of symbols*/ + + error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen); + if(!error) error = HuffmanTree_makeFromLengths2(tree); + return error; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/ +static unsigned generateFixedLitLenTree(HuffmanTree* tree) { + unsigned i, error = 0; + unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + if(!bitlen) return 83; /*alloc fail*/ + + /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ + for(i = 0; i <= 143; ++i) bitlen[i] = 8; + for(i = 144; i <= 255; ++i) bitlen[i] = 9; + for(i = 256; i <= 279; ++i) bitlen[i] = 7; + for(i = 280; i <= 287; ++i) bitlen[i] = 8; + + error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15); + + lodepng_free(bitlen); + return error; +} + +/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/ +static unsigned generateFixedDistanceTree(HuffmanTree* tree) { + unsigned i, error = 0; + unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); + if(!bitlen) return 83; /*alloc fail*/ + + /*there are 32 distance codes, but 30-31 are unused*/ + for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5; + error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15); + + lodepng_free(bitlen); + return error; +} + +#ifdef LODEPNG_COMPILE_DECODER + +/* +returns the code. The bit reader must already have been ensured at least 15 bits +*/ +static unsigned huffmanDecodeSymbol(LodePNGBitReader* reader, const HuffmanTree* codetree) { + unsigned short code = peekBits(reader, FIRSTBITS); + unsigned short l = codetree->table_len[code]; + unsigned short value = codetree->table_value[code]; + if(l <= FIRSTBITS) { + advanceBits(reader, l); + return value; + } else { + advanceBits(reader, FIRSTBITS); + value += peekBits(reader, l - FIRSTBITS); + advanceBits(reader, codetree->table_len[value] - FIRSTBITS); + return codetree->table_value[value]; + } +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Inflator (Decompressor) / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*get the tree of a deflated block with fixed tree, as specified in the deflate specification +Returns error code.*/ +static unsigned getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) { + unsigned error = generateFixedLitLenTree(tree_ll); + if(error) return error; + return generateFixedDistanceTree(tree_d); +} + +/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ +static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d, + LodePNGBitReader* reader) { + /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/ + unsigned error = 0; + unsigned n, HLIT, HDIST, HCLEN, i; + + /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/ + unsigned* bitlen_ll = 0; /*lit,len code lengths*/ + unsigned* bitlen_d = 0; /*dist code lengths*/ + /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/ + unsigned* bitlen_cl = 0; + HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/ + + if(reader->bitsize - reader->bp < 14) return 49; /*error: the bit pointer is or will go past the memory*/ + ensureBits17(reader, 14); + + /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/ + HLIT = readBits(reader, 5) + 257; + /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/ + HDIST = readBits(reader, 5) + 1; + /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/ + HCLEN = readBits(reader, 4) + 4; + + bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned)); + if(!bitlen_cl) return 83 /*alloc fail*/; + + HuffmanTree_init(&tree_cl); + + while(!error) { + /*read the code length codes out of 3 * (amount of code length codes) bits*/ + if(lodepng_gtofl(reader->bp, HCLEN * 3, reader->bitsize)) { + ERROR_BREAK(50); /*error: the bit pointer is or will go past the memory*/ + } + for(i = 0; i != HCLEN; ++i) { + ensureBits9(reader, 3); /*out of bounds already checked above */ + bitlen_cl[CLCL_ORDER[i]] = readBits(reader, 3); + } + for(i = HCLEN; i != NUM_CODE_LENGTH_CODES; ++i) { + bitlen_cl[CLCL_ORDER[i]] = 0; + } + + error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7); + if(error) break; + + /*now we can use this tree to read the lengths for the tree that this function will return*/ + bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); + if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/); + lodepng_memset(bitlen_ll, 0, NUM_DEFLATE_CODE_SYMBOLS * sizeof(*bitlen_ll)); + lodepng_memset(bitlen_d, 0, NUM_DISTANCE_SYMBOLS * sizeof(*bitlen_d)); + + /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/ + i = 0; + while(i < HLIT + HDIST) { + unsigned code; + ensureBits25(reader, 22); /* up to 15 bits for huffman code, up to 7 extra bits below*/ + code = huffmanDecodeSymbol(reader, &tree_cl); + if(code <= 15) /*a length code*/ { + if(i < HLIT) bitlen_ll[i] = code; + else bitlen_d[i - HLIT] = code; + ++i; + } else if(code == 16) /*repeat previous*/ { + unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/ + unsigned value; /*set value to the previous code*/ + + if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/ + + replength += readBits(reader, 2); + + if(i < HLIT + 1) value = bitlen_ll[i - 1]; + else value = bitlen_d[i - HLIT - 1]; + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) { + if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/ + if(i < HLIT) bitlen_ll[i] = value; + else bitlen_d[i - HLIT] = value; + ++i; + } + } else if(code == 17) /*repeat "0" 3-10 times*/ { + unsigned replength = 3; /*read in the bits that indicate repeat length*/ + replength += readBits(reader, 3); + + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) { + if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/ + + if(i < HLIT) bitlen_ll[i] = 0; + else bitlen_d[i - HLIT] = 0; + ++i; + } + } else if(code == 18) /*repeat "0" 11-138 times*/ { + unsigned replength = 11; /*read in the bits that indicate repeat length*/ + replength += readBits(reader, 7); + + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) { + if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/ + + if(i < HLIT) bitlen_ll[i] = 0; + else bitlen_d[i - HLIT] = 0; + ++i; + } + } else /*if(code == INVALIDSYMBOL)*/ { + ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ + } + /*check if any of the ensureBits above went out of bounds*/ + if(reader->bp > reader->bitsize) { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ + ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ + } + } + if(error) break; + + if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/ + + /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/ + error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15); + if(error) break; + error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15); + + break; /*end of error-while*/ + } + + lodepng_free(bitlen_cl); + lodepng_free(bitlen_ll); + lodepng_free(bitlen_d); + HuffmanTree_cleanup(&tree_cl); + + return error; +} + +/*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/ +static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader, + unsigned btype, size_t max_output_size) { + unsigned error = 0; + HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/ + HuffmanTree tree_d; /*the huffman tree for distance codes*/ + const size_t reserved_size = 260; /* must be at least 258 for max length, and a few extra for adding a few extra literals */ + int done = 0; + + if(!ucvector_reserve(out, out->size + reserved_size)) return 83; /*alloc fail*/ + + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + + if(btype == 1) error = getTreeInflateFixed(&tree_ll, &tree_d); + else /*if(btype == 2)*/ error = getTreeInflateDynamic(&tree_ll, &tree_d, reader); + + + while(!error && !done) /*decode all symbols until end reached, breaks at end code*/ { + /*code_ll is literal, length or end code*/ + unsigned code_ll; + /* ensure enough bits for 2 huffman code reads (15 bits each): if the first is a literal, a second literal is read at once. This + appears to be slightly faster, than ensuring 20 bits here for 1 huffman symbol and the potential 5 extra bits for the length symbol.*/ + ensureBits32(reader, 30); + code_ll = huffmanDecodeSymbol(reader, &tree_ll); + if(code_ll <= 255) { + /*slightly faster code path if multiple literals in a row*/ + out->data[out->size++] = (unsigned char)code_ll; + code_ll = huffmanDecodeSymbol(reader, &tree_ll); + } + if(code_ll <= 255) /*literal symbol*/ { + out->data[out->size++] = (unsigned char)code_ll; + } else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ { + unsigned code_d, distance; + unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/ + size_t start, backward, length; + + /*part 1: get length base*/ + length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX]; + + /*part 2: get extra bits and add the value of that to length*/ + numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX]; + if(numextrabits_l != 0) { + /* bits already ensured above */ + ensureBits25(reader, 5); + length += readBits(reader, numextrabits_l); + } + + /*part 3: get distance code*/ + ensureBits32(reader, 28); /* up to 15 for the huffman symbol, up to 13 for the extra bits */ + code_d = huffmanDecodeSymbol(reader, &tree_d); + if(code_d > 29) { + if(code_d <= 31) { + ERROR_BREAK(18); /*error: invalid distance code (30-31 are never used)*/ + } else /* if(code_d == INVALIDSYMBOL) */{ + ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ + } + } + distance = DISTANCEBASE[code_d]; + + /*part 4: get extra bits from distance*/ + numextrabits_d = DISTANCEEXTRA[code_d]; + if(numextrabits_d != 0) { + /* bits already ensured above */ + distance += readBits(reader, numextrabits_d); + } + + /*part 5: fill in all the out[n] values based on the length and dist*/ + start = out->size; + if(distance > start) ERROR_BREAK(52); /*too long backward distance*/ + backward = start - distance; + + out->size += length; + if(distance < length) { + size_t forward; + lodepng_memcpy(out->data + start, out->data + backward, distance); + start += distance; + for(forward = distance; forward < length; ++forward) { + out->data[start++] = out->data[backward++]; + } + } else { + lodepng_memcpy(out->data + start, out->data + backward, length); + } + } else if(code_ll == 256) { + done = 1; /*end code, finish the loop*/ + } else /*if(code_ll == INVALIDSYMBOL)*/ { + ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ + } + if(out->allocsize - out->size < reserved_size) { + if(!ucvector_reserve(out, out->size + reserved_size)) ERROR_BREAK(83); /*alloc fail*/ + } + /*check if any of the ensureBits above went out of bounds*/ + if(reader->bp > reader->bitsize) { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ + ERROR_BREAK(51); /*error, bit pointer jumps past memory*/ + } + if(max_output_size && out->size > max_output_size) { + ERROR_BREAK(109); /*error, larger than max size*/ + } + } + + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + + return error; +} + +static unsigned inflateNoCompression(ucvector* out, LodePNGBitReader* reader, + const LodePNGDecompressSettings* settings) { + size_t bytepos; + size_t size = reader->size; + unsigned LEN, NLEN, error = 0; + + /*go to first boundary of byte*/ + bytepos = (reader->bp + 7u) >> 3u; + + /*read LEN (2 bytes) and NLEN (2 bytes)*/ + if(bytepos + 4 >= size) return 52; /*error, bit pointer will jump past memory*/ + LEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); bytepos += 2; + NLEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); bytepos += 2; + + /*check if 16-bit NLEN is really the one's complement of LEN*/ + if(!settings->ignore_nlen && LEN + NLEN != 65535) { + return 21; /*error: NLEN is not one's complement of LEN*/ + } + + if(!ucvector_resize(out, out->size + LEN)) return 83; /*alloc fail*/ + + /*read the literal data: LEN bytes are now stored in the out buffer*/ + if(bytepos + LEN > size) return 23; /*error: reading outside of in buffer*/ + + /*out->data can be NULL (when LEN is zero), and arithmetics on NULL ptr is undefined*/ + if (LEN) { + lodepng_memcpy(out->data + out->size - LEN, reader->data + bytepos, LEN); + bytepos += LEN; + } + + reader->bp = bytepos << 3u; + + return error; +} + +static unsigned lodepng_inflatev(ucvector* out, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) { + unsigned BFINAL = 0; + LodePNGBitReader reader; + unsigned error = LodePNGBitReader_init(&reader, in, insize); + + if(error) return error; + + while(!BFINAL) { + unsigned BTYPE; + if(reader.bitsize - reader.bp < 3) return 52; /*error, bit pointer will jump past memory*/ + ensureBits9(&reader, 3); + BFINAL = readBits(&reader, 1); + BTYPE = readBits(&reader, 2); + + if(BTYPE == 3) return 20; /*error: invalid BTYPE*/ + else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/ + else error = inflateHuffmanBlock(out, &reader, BTYPE, settings->max_output_size); /*compression, BTYPE 01 or 10*/ + if(!error && settings->max_output_size && out->size > settings->max_output_size) error = 109; + if(error) break; + } + + return error; +} + +unsigned lodepng_inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) { + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_inflatev(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +static unsigned inflatev(ucvector* out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) { + if(settings->custom_inflate) { + unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings); + out->allocsize = out->size; + if(error) { + /*the custom inflate is allowed to have its own error codes, however, we translate it to code 110*/ + error = 110; + /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ + if(settings->max_output_size && out->size > settings->max_output_size) error = 109; + } + return error; + } else { + return lodepng_inflatev(out, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Deflator (Compressor) / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258; + +/*search the index in the array, that has the largest value smaller than or equal to the given value, +given array must be sorted (if no value is smaller, it returns the size of the given array)*/ +static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) { + /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/ + size_t left = 1; + size_t right = array_size - 1; + + while(left <= right) { + size_t mid = (left + right) >> 1; + if(array[mid] >= value) right = mid - 1; + else left = mid + 1; + } + if(left >= array_size || array[left] > value) left--; + return left; +} + +static void addLengthDistance(uivector* values, size_t length, size_t distance) { + /*values in encoded vector are those used by deflate: + 0-255: literal bytes + 256: end + 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) + 286-287: invalid*/ + + unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); + unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); + unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); + unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); + + size_t pos = values->size; + /*TODO: return error when this fails (out of memory)*/ + unsigned ok = uivector_resize(values, values->size + 4); + if(ok) { + values->data[pos + 0] = length_code + FIRST_LENGTH_CODE_INDEX; + values->data[pos + 1] = extra_length; + values->data[pos + 2] = dist_code; + values->data[pos + 3] = extra_distance; + } +} + +/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3 +bytes as input because 3 is the minimum match length for deflate*/ +static const unsigned HASH_NUM_VALUES = 65536; +static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/ + +typedef struct Hash { + int* head; /*hash value to head circular pos - can be outdated if went around window*/ + /*circular pos to prev circular pos*/ + unsigned short* chain; + int* val; /*circular pos to hash value*/ + + /*TODO: do this not only for zeros but for any repeated byte. However for PNG + it's always going to be the zeros that dominate, so not important for PNG*/ + int* headz; /*similar to head, but for chainz*/ + unsigned short* chainz; /*those with same amount of zeros*/ + unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/ +} Hash; + +static unsigned hash_init(Hash* hash, unsigned windowsize) { + unsigned i; + hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES); + hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize); + hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + + hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1)); + hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + + if(!hash->head || !hash->chain || !hash->val || !hash->headz|| !hash->chainz || !hash->zeros) { + return 83; /*alloc fail*/ + } + + /*initialize hash table*/ + for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1; + for(i = 0; i != windowsize; ++i) hash->val[i] = -1; + for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/ + + for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1; + for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/ + + return 0; +} + +static void hash_cleanup(Hash* hash) { + lodepng_free(hash->head); + lodepng_free(hash->val); + lodepng_free(hash->chain); + + lodepng_free(hash->zeros); + lodepng_free(hash->headz); + lodepng_free(hash->chainz); +} + + + +static unsigned getHash(const unsigned char* data, size_t size, size_t pos) { + unsigned result = 0; + if(pos + 2 < size) { + /*A simple shift and xor hash is used. Since the data of PNGs is dominated + by zeroes due to the filters, a better hash does not have a significant + effect on speed in traversing the chain, and causes more time spend on + calculating the hash.*/ + result ^= ((unsigned)data[pos + 0] << 0u); + result ^= ((unsigned)data[pos + 1] << 4u); + result ^= ((unsigned)data[pos + 2] << 8u); + } else { + size_t amount, i; + if(pos >= size) return 0; + amount = size - pos; + for(i = 0; i != amount; ++i) result ^= ((unsigned)data[pos + i] << (i * 8u)); + } + return result & HASH_BIT_MASK; +} + +static unsigned countZeros(const unsigned char* data, size_t size, size_t pos) { + const unsigned char* start = data + pos; + const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH; + if(end > data + size) end = data + size; + data = start; + while(data != end && *data == 0) ++data; + /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/ + return (unsigned)(data - start); +} + +/*wpos = pos & (windowsize - 1)*/ +static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros) { + hash->val[wpos] = (int)hashval; + if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval]; + hash->head[hashval] = (int)wpos; + + hash->zeros[wpos] = numzeros; + if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros]; + hash->headz[numzeros] = (int)wpos; +} + +/* +LZ77-encode the data. Return value is error code. The input are raw bytes, the output +is in the form of unsigned integers with codes representing for example literal bytes, or +length/distance pairs. +It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a +sliding window (of windowsize) is used, and all past bytes in that window can be used as +the "dictionary". A brute force search through all possible distances would be slow, and +this hash technique is one out of several ways to speed this up. +*/ +static unsigned encodeLZ77(uivector* out, Hash* hash, + const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize, + unsigned minmatch, unsigned nicematch, unsigned lazymatching) { + size_t pos; + unsigned i, error = 0; + /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/ + unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8u; + unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64; + + unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/ + unsigned numzeros = 0; + + unsigned offset; /*the offset represents the distance in LZ77 terminology*/ + unsigned length; + unsigned lazy = 0; + unsigned lazylength = 0, lazyoffset = 0; + unsigned hashval; + unsigned current_offset, current_length; + unsigned prev_offset; + const unsigned char *lastptr, *foreptr, *backptr; + unsigned hashpos; + + if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/ + if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/ + + if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH; + + for(pos = inpos; pos < insize; ++pos) { + size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/ + unsigned chainlength = 0; + + hashval = getHash(in, insize, pos); + + if(usezeros && hashval == 0) { + if(numzeros == 0) numzeros = countZeros(in, insize, pos); + else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; + } else { + numzeros = 0; + } + + updateHashChain(hash, wpos, hashval, numzeros); + + /*the length and offset found for the current position*/ + length = 0; + offset = 0; + + hashpos = hash->chain[wpos]; + + lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH]; + + /*search for the longest string*/ + prev_offset = 0; + for(;;) { + if(chainlength++ >= maxchainlength) break; + current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize); + + if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/ + prev_offset = current_offset; + if(current_offset > 0) { + /*test the next characters*/ + foreptr = &in[pos]; + backptr = &in[pos - current_offset]; + + /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/ + if(numzeros >= 3) { + unsigned skip = hash->zeros[hashpos]; + if(skip > numzeros) skip = numzeros; + backptr += skip; + foreptr += skip; + } + + while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/ { + ++backptr; + ++foreptr; + } + current_length = (unsigned)(foreptr - &in[pos]); + + if(current_length > length) { + length = current_length; /*the longest length*/ + offset = current_offset; /*the offset that is related to this longest length*/ + /*jump out once a length of max length is found (speed gain). This also jumps + out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/ + if(current_length >= nicematch) break; + } + } + + if(hashpos == hash->chain[hashpos]) break; + + if(numzeros >= 3 && length > numzeros) { + hashpos = hash->chainz[hashpos]; + if(hash->zeros[hashpos] != numzeros) break; + } else { + hashpos = hash->chain[hashpos]; + /*outdated hash value, happens if particular value was not encountered in whole last window*/ + if(hash->val[hashpos] != (int)hashval) break; + } + } + + if(lazymatching) { + if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) { + lazy = 1; + lazylength = length; + lazyoffset = offset; + continue; /*try the next byte*/ + } + if(lazy) { + lazy = 0; + if(pos == 0) ERROR_BREAK(81); + if(length > lazylength + 1) { + /*push the previous character as literal*/ + if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/); + } else { + length = lazylength; + offset = lazyoffset; + hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/ + hash->headz[numzeros] = -1; /*idem*/ + --pos; + } + } + } + if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/); + + /*encode it as length/distance pair or literal value*/ + if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ { + if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); + } else if(length < minmatch || (length == 3 && offset > 4096)) { + /*compensate for the fact that longer offsets have more extra bits, a + length of only 3 may be not worth it then*/ + if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); + } else { + addLengthDistance(out, length, offset); + for(i = 1; i < length; ++i) { + ++pos; + wpos = pos & (windowsize - 1); + hashval = getHash(in, insize, pos); + if(usezeros && hashval == 0) { + if(numzeros == 0) numzeros = countZeros(in, insize, pos); + else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; + } else { + numzeros = 0; + } + updateHashChain(hash, wpos, hashval, numzeros); + } + } + } /*end of the loop through each character of input*/ + + return error; +} + +/* /////////////////////////////////////////////////////////////////////////// */ + +static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) { + /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, + 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ + + size_t i, numdeflateblocks = (datasize + 65534u) / 65535u; + unsigned datapos = 0; + for(i = 0; i != numdeflateblocks; ++i) { + unsigned BFINAL, BTYPE, LEN, NLEN; + unsigned char firstbyte; + size_t pos = out->size; + + BFINAL = (i == numdeflateblocks - 1); + BTYPE = 0; + + LEN = 65535; + if(datasize - datapos < 65535u) LEN = (unsigned)datasize - datapos; + NLEN = 65535 - LEN; + + if(!ucvector_resize(out, out->size + LEN + 5)) return 83; /*alloc fail*/ + + firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1u) << 1u) + ((BTYPE & 2u) << 1u)); + out->data[pos + 0] = firstbyte; + out->data[pos + 1] = (unsigned char)(LEN & 255); + out->data[pos + 2] = (unsigned char)(LEN >> 8u); + out->data[pos + 3] = (unsigned char)(NLEN & 255); + out->data[pos + 4] = (unsigned char)(NLEN >> 8u); + lodepng_memcpy(out->data + pos + 5, data + datapos, LEN); + datapos += LEN; + } + + return 0; +} + +/* +write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees. +tree_ll: the tree for lit and len codes. +tree_d: the tree for distance codes. +*/ +static void writeLZ77data(LodePNGBitWriter* writer, const uivector* lz77_encoded, + const HuffmanTree* tree_ll, const HuffmanTree* tree_d) { + size_t i = 0; + for(i = 0; i != lz77_encoded->size; ++i) { + unsigned val = lz77_encoded->data[i]; + writeBitsReversed(writer, tree_ll->codes[val], tree_ll->lengths[val]); + if(val > 256) /*for a length code, 3 more things have to be added*/ { + unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; + unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; + unsigned length_extra_bits = lz77_encoded->data[++i]; + + unsigned distance_code = lz77_encoded->data[++i]; + + unsigned distance_index = distance_code; + unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; + unsigned distance_extra_bits = lz77_encoded->data[++i]; + + writeBits(writer, length_extra_bits, n_length_extra_bits); + writeBitsReversed(writer, tree_d->codes[distance_code], tree_d->lengths[distance_code]); + writeBits(writer, distance_extra_bits, n_distance_extra_bits); + } + } +} + +/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/ +static unsigned deflateDynamic(LodePNGBitWriter* writer, Hash* hash, + const unsigned char* data, size_t datapos, size_t dataend, + const LodePNGCompressSettings* settings, unsigned final) { + unsigned error = 0; + + /* + A block is compressed as follows: The PNG data is lz77 encoded, resulting in + literal bytes and length/distance pairs. This is then huffman compressed with + two huffman trees. One huffman tree is used for the lit and len values ("ll"), + another huffman tree is used for the dist values ("d"). These two trees are + stored using their code lengths, and to compress even more these code lengths + are also run-length encoded and huffman compressed. This gives a huffman tree + of code lengths "cl". The code lengths used to describe this third tree are + the code length code lengths ("clcl"). + */ + + /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/ + uivector lz77_encoded; + HuffmanTree tree_ll; /*tree for lit,len values*/ + HuffmanTree tree_d; /*tree for distance codes*/ + HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/ + unsigned* frequencies_ll = 0; /*frequency of lit,len codes*/ + unsigned* frequencies_d = 0; /*frequency of dist codes*/ + unsigned* frequencies_cl = 0; /*frequency of code length codes*/ + unsigned* bitlen_lld = 0; /*lit,len,dist code lengths (int bits), literally (without repeat codes).*/ + unsigned* bitlen_lld_e = 0; /*bitlen_lld encoded with repeat codes (this is a rudimentary run length compression)*/ + size_t datasize = dataend - datapos; + + /* + If we could call "bitlen_cl" the the code length code lengths ("clcl"), that is the bit lengths of codes to represent + tree_cl in CLCL_ORDER, then due to the huffman compression of huffman tree representations ("two levels"), there are + some analogies: + bitlen_lld is to tree_cl what data is to tree_ll and tree_d. + bitlen_lld_e is to bitlen_lld what lz77_encoded is to data. + bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded. + */ + + unsigned BFINAL = final; + size_t i; + size_t numcodes_ll, numcodes_d, numcodes_lld, numcodes_lld_e, numcodes_cl; + unsigned HLIT, HDIST, HCLEN; + + uivector_init(&lz77_encoded); + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + HuffmanTree_init(&tree_cl); + /* could fit on stack, but >1KB is on the larger side so allocate instead */ + frequencies_ll = (unsigned*)lodepng_malloc(286 * sizeof(*frequencies_ll)); + frequencies_d = (unsigned*)lodepng_malloc(30 * sizeof(*frequencies_d)); + frequencies_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl)); + + if(!frequencies_ll || !frequencies_d || !frequencies_cl) error = 83; /*alloc fail*/ + + /*This while loop never loops due to a break at the end, it is here to + allow breaking out of it to the cleanup phase on error conditions.*/ + while(!error) { + lodepng_memset(frequencies_ll, 0, 286 * sizeof(*frequencies_ll)); + lodepng_memset(frequencies_d, 0, 30 * sizeof(*frequencies_d)); + lodepng_memset(frequencies_cl, 0, NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl)); + + if(settings->use_lz77) { + error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, + settings->minmatch, settings->nicematch, settings->lazymatching); + if(error) break; + } else { + if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/); + for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/ + } + + /*Count the frequencies of lit, len and dist codes*/ + for(i = 0; i != lz77_encoded.size; ++i) { + unsigned symbol = lz77_encoded.data[i]; + ++frequencies_ll[symbol]; + if(symbol > 256) { + unsigned dist = lz77_encoded.data[i + 2]; + ++frequencies_d[dist]; + i += 3; + } + } + frequencies_ll[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ + + /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/ + error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll, 257, 286, 15); + if(error) break; + /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/ + error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d, 2, 30, 15); + if(error) break; + + numcodes_ll = LODEPNG_MIN(tree_ll.numcodes, 286); + numcodes_d = LODEPNG_MIN(tree_d.numcodes, 30); + /*store the code lengths of both generated trees in bitlen_lld*/ + numcodes_lld = numcodes_ll + numcodes_d; + bitlen_lld = (unsigned*)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld)); + /*numcodes_lld_e never needs more size than bitlen_lld*/ + bitlen_lld_e = (unsigned*)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld_e)); + if(!bitlen_lld || !bitlen_lld_e) ERROR_BREAK(83); /*alloc fail*/ + numcodes_lld_e = 0; + + for(i = 0; i != numcodes_ll; ++i) bitlen_lld[i] = tree_ll.lengths[i]; + for(i = 0; i != numcodes_d; ++i) bitlen_lld[numcodes_ll + i] = tree_d.lengths[i]; + + /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times), + 17 (3-10 zeroes), 18 (11-138 zeroes)*/ + for(i = 0; i != numcodes_lld; ++i) { + unsigned j = 0; /*amount of repetitions*/ + while(i + j + 1 < numcodes_lld && bitlen_lld[i + j + 1] == bitlen_lld[i]) ++j; + + if(bitlen_lld[i] == 0 && j >= 2) /*repeat code for zeroes*/ { + ++j; /*include the first zero*/ + if(j <= 10) /*repeat code 17 supports max 10 zeroes*/ { + bitlen_lld_e[numcodes_lld_e++] = 17; + bitlen_lld_e[numcodes_lld_e++] = j - 3; + } else /*repeat code 18 supports max 138 zeroes*/ { + if(j > 138) j = 138; + bitlen_lld_e[numcodes_lld_e++] = 18; + bitlen_lld_e[numcodes_lld_e++] = j - 11; + } + i += (j - 1); + } else if(j >= 3) /*repeat code for value other than zero*/ { + size_t k; + unsigned num = j / 6u, rest = j % 6u; + bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i]; + for(k = 0; k < num; ++k) { + bitlen_lld_e[numcodes_lld_e++] = 16; + bitlen_lld_e[numcodes_lld_e++] = 6 - 3; + } + if(rest >= 3) { + bitlen_lld_e[numcodes_lld_e++] = 16; + bitlen_lld_e[numcodes_lld_e++] = rest - 3; + } + else j -= rest; + i += j; + } else /*too short to benefit from repeat code*/ { + bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i]; + } + } + + /*generate tree_cl, the huffmantree of huffmantrees*/ + for(i = 0; i != numcodes_lld_e; ++i) { + ++frequencies_cl[bitlen_lld_e[i]]; + /*after a repeat code come the bits that specify the number of repetitions, + those don't need to be in the frequencies_cl calculation*/ + if(bitlen_lld_e[i] >= 16) ++i; + } + + error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl, + NUM_CODE_LENGTH_CODES, NUM_CODE_LENGTH_CODES, 7); + if(error) break; + + /*compute amount of code-length-code-lengths to output*/ + numcodes_cl = NUM_CODE_LENGTH_CODES; + /*trim zeros at the end (using CLCL_ORDER), but minimum size must be 4 (see HCLEN below)*/ + while(numcodes_cl > 4u && tree_cl.lengths[CLCL_ORDER[numcodes_cl - 1u]] == 0) { + numcodes_cl--; + } + + /* + Write everything into the output + + After the BFINAL and BTYPE, the dynamic block consists out of the following: + - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN + - (HCLEN+4)*3 bits code lengths of code length alphabet + - HLIT + 257 code lengths of lit/length alphabet (encoded using the code length + alphabet, + possible repetition codes 16, 17, 18) + - HDIST + 1 code lengths of distance alphabet (encoded using the code length + alphabet, + possible repetition codes 16, 17, 18) + - compressed data + - 256 (end code) + */ + + /*Write block type*/ + writeBits(writer, BFINAL, 1); + writeBits(writer, 0, 1); /*first bit of BTYPE "dynamic"*/ + writeBits(writer, 1, 1); /*second bit of BTYPE "dynamic"*/ + + /*write the HLIT, HDIST and HCLEN values*/ + /*all three sizes take trimmed ending zeroes into account, done either by HuffmanTree_makeFromFrequencies + or in the loop for numcodes_cl above, which saves space. */ + HLIT = (unsigned)(numcodes_ll - 257); + HDIST = (unsigned)(numcodes_d - 1); + HCLEN = (unsigned)(numcodes_cl - 4); + writeBits(writer, HLIT, 5); + writeBits(writer, HDIST, 5); + writeBits(writer, HCLEN, 4); + + /*write the code lengths of the code length alphabet ("bitlen_cl")*/ + for(i = 0; i != numcodes_cl; ++i) writeBits(writer, tree_cl.lengths[CLCL_ORDER[i]], 3); + + /*write the lengths of the lit/len AND the dist alphabet*/ + for(i = 0; i != numcodes_lld_e; ++i) { + writeBitsReversed(writer, tree_cl.codes[bitlen_lld_e[i]], tree_cl.lengths[bitlen_lld_e[i]]); + /*extra bits of repeat codes*/ + if(bitlen_lld_e[i] == 16) writeBits(writer, bitlen_lld_e[++i], 2); + else if(bitlen_lld_e[i] == 17) writeBits(writer, bitlen_lld_e[++i], 3); + else if(bitlen_lld_e[i] == 18) writeBits(writer, bitlen_lld_e[++i], 7); + } + + /*write the compressed data symbols*/ + writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d); + /*error: the length of the end code 256 must be larger than 0*/ + if(tree_ll.lengths[256] == 0) ERROR_BREAK(64); + + /*write the end code*/ + writeBitsReversed(writer, tree_ll.codes[256], tree_ll.lengths[256]); + + break; /*end of error-while*/ + } + + /*cleanup*/ + uivector_cleanup(&lz77_encoded); + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + HuffmanTree_cleanup(&tree_cl); + lodepng_free(frequencies_ll); + lodepng_free(frequencies_d); + lodepng_free(frequencies_cl); + lodepng_free(bitlen_lld); + lodepng_free(bitlen_lld_e); + + return error; +} + +static unsigned deflateFixed(LodePNGBitWriter* writer, Hash* hash, + const unsigned char* data, + size_t datapos, size_t dataend, + const LodePNGCompressSettings* settings, unsigned final) { + HuffmanTree tree_ll; /*tree for literal values and length codes*/ + HuffmanTree tree_d; /*tree for distance codes*/ + + unsigned BFINAL = final; + unsigned error = 0; + size_t i; + + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + + error = generateFixedLitLenTree(&tree_ll); + if(!error) error = generateFixedDistanceTree(&tree_d); + + if(!error) { + writeBits(writer, BFINAL, 1); + writeBits(writer, 1, 1); /*first bit of BTYPE*/ + writeBits(writer, 0, 1); /*second bit of BTYPE*/ + + if(settings->use_lz77) /*LZ77 encoded*/ { + uivector lz77_encoded; + uivector_init(&lz77_encoded); + error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, + settings->minmatch, settings->nicematch, settings->lazymatching); + if(!error) writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d); + uivector_cleanup(&lz77_encoded); + } else /*no LZ77, but still will be Huffman compressed*/ { + for(i = datapos; i < dataend; ++i) { + writeBitsReversed(writer, tree_ll.codes[data[i]], tree_ll.lengths[data[i]]); + } + } + /*add END code*/ + if(!error) writeBitsReversed(writer,tree_ll.codes[256], tree_ll.lengths[256]); + } + + /*cleanup*/ + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + + return error; +} + +static unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) { + unsigned error = 0; + size_t i, blocksize, numdeflateblocks; + Hash hash; + LodePNGBitWriter writer; + + LodePNGBitWriter_init(&writer, out); + + if(settings->btype > 2) return 61; + else if(settings->btype == 0) return deflateNoCompression(out, in, insize); + else if(settings->btype == 1) blocksize = insize; + else /*if(settings->btype == 2)*/ { + /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/ + blocksize = insize / 8u + 8; + if(blocksize < 65536) blocksize = 65536; + if(blocksize > 262144) blocksize = 262144; + } + + numdeflateblocks = (insize + blocksize - 1) / blocksize; + if(numdeflateblocks == 0) numdeflateblocks = 1; + + error = hash_init(&hash, settings->windowsize); + + if(!error) { + for(i = 0; i != numdeflateblocks && !error; ++i) { + unsigned final = (i == numdeflateblocks - 1); + size_t start = i * blocksize; + size_t end = start + blocksize; + if(end > insize) end = insize; + + if(settings->btype == 1) error = deflateFixed(&writer, &hash, in, start, end, settings, final); + else if(settings->btype == 2) error = deflateDynamic(&writer, &hash, in, start, end, settings, final); + } + } + + hash_cleanup(&hash); + + return error; +} + +unsigned lodepng_deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) { + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_deflatev(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +static unsigned deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) { + if(settings->custom_deflate) { + unsigned error = settings->custom_deflate(out, outsize, in, insize, settings); + /*the custom deflate is allowed to have its own error codes, however, we translate it to code 111*/ + return error ? 111 : 0; + } else { + return lodepng_deflate(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Adler32 / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) { + unsigned s1 = adler & 0xffffu; + unsigned s2 = (adler >> 16u) & 0xffffu; + + while(len != 0u) { + unsigned i; + /*at least 5552 sums can be done before the sums overflow, saving a lot of module divisions*/ + unsigned amount = len > 5552u ? 5552u : len; + len -= amount; + for(i = 0; i != amount; ++i) { + s1 += (*data++); + s2 += s1; + } + s1 %= 65521u; + s2 %= 65521u; + } + + return (s2 << 16u) | s1; +} + +/*Return the adler32 of the bytes data[0..len-1]*/ +static unsigned adler32(const unsigned char* data, unsigned len) { + return update_adler32(1u, data, len); +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Zlib / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_DECODER + +static unsigned lodepng_zlib_decompressv(ucvector* out, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) { + unsigned error = 0; + unsigned CM, CINFO, FDICT; + + if(insize < 2) return 53; /*error, size of zlib data too small*/ + /*read information from zlib header*/ + if((in[0] * 256 + in[1]) % 31 != 0) { + /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/ + return 24; + } + + CM = in[0] & 15; + CINFO = (in[0] >> 4) & 15; + /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/ + FDICT = (in[1] >> 5) & 1; + /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/ + + if(CM != 8 || CINFO > 7) { + /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/ + return 25; + } + if(FDICT != 0) { + /*error: the specification of PNG says about the zlib stream: + "The additional flags shall not specify a preset dictionary."*/ + return 26; + } + + error = inflatev(out, in + 2, insize - 2, settings); + if(error) return error; + + if(!settings->ignore_adler32) { + unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]); + unsigned checksum = adler32(out->data, (unsigned)(out->size)); + if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/ + } + + return 0; /*no error*/ +} + + +unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGDecompressSettings* settings) { + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_zlib_decompressv(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +/*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */ +static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size, + const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) { + unsigned error; + if(settings->custom_zlib) { + error = settings->custom_zlib(out, outsize, in, insize, settings); + if(error) { + /*the custom zlib is allowed to have its own error codes, however, we translate it to code 110*/ + error = 110; + /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ + if(settings->max_output_size && *outsize > settings->max_output_size) error = 109; + } + } else { + ucvector v = ucvector_init(*out, *outsize); + if(expected_size) { + /*reserve the memory to avoid intermediate reallocations*/ + ucvector_resize(&v, *outsize + expected_size); + v.size = *outsize; + } + error = lodepng_zlib_decompressv(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + } + return error; +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER + +unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) { + size_t i; + unsigned error; + unsigned char* deflatedata = 0; + size_t deflatesize = 0; + + error = deflate(&deflatedata, &deflatesize, in, insize, settings); + + *out = NULL; + *outsize = 0; + if(!error) { + *outsize = deflatesize + 6; + *out = (unsigned char*)lodepng_malloc(*outsize); + if(!*out) error = 83; /*alloc fail*/ + } + + if(!error) { + unsigned ADLER32 = adler32(in, (unsigned)insize); + /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ + unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ + unsigned FLEVEL = 0; + unsigned FDICT = 0; + unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; + unsigned FCHECK = 31 - CMFFLG % 31; + CMFFLG += FCHECK; + + (*out)[0] = (unsigned char)(CMFFLG >> 8); + (*out)[1] = (unsigned char)(CMFFLG & 255); + for(i = 0; i != deflatesize; ++i) (*out)[i + 2] = deflatedata[i]; + lodepng_set32bitInt(&(*out)[*outsize - 4], ADLER32); + } + + lodepng_free(deflatedata); + return error; +} + +/* compress using the default or custom zlib function */ +static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) { + if(settings->custom_zlib) { + unsigned error = settings->custom_zlib(out, outsize, in, insize, settings); + /*the custom zlib is allowed to have its own error codes, however, we translate it to code 111*/ + return error ? 111 : 0; + } else { + return lodepng_zlib_compress(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#else /*no LODEPNG_COMPILE_ZLIB*/ + +#ifdef LODEPNG_COMPILE_DECODER +static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size, + const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) { + if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ + (void)expected_size; + return settings->custom_zlib(out, outsize, in, insize, settings); +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER +static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) { + if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ + return settings->custom_zlib(out, outsize, in, insize, settings); +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#endif /*LODEPNG_COMPILE_ZLIB*/ + +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_ENCODER + +/*this is a good tradeoff between speed and compression ratio*/ +#define DEFAULT_WINDOWSIZE 2048 + +void lodepng_compress_settings_init(LodePNGCompressSettings* settings) { + /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ + settings->btype = 2; + settings->use_lz77 = 1; + settings->windowsize = DEFAULT_WINDOWSIZE; + settings->minmatch = 3; + settings->nicematch = 128; + settings->lazymatching = 1; + + settings->custom_zlib = 0; + settings->custom_deflate = 0; + settings->custom_context = 0; +} + +const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0}; + + +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) { + settings->ignore_adler32 = 0; + settings->ignore_nlen = 0; + settings->max_output_size = 0; + + settings->custom_zlib = 0; + settings->custom_inflate = 0; + settings->custom_context = 0; +} + +const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0, 0}; + +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // End of Zlib related code. Begin of PNG related code. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_PNG + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / CRC32 / */ +/* ////////////////////////////////////////////////////////////////////////// */ + + +#ifdef LODEPNG_COMPILE_CRC + +static const unsigned lodepng_crc32_table0[256] = { + 0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u, + 0x0edb8832u, 0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u, + 0x1db71064u, 0x6ab020f2u, 0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u, + 0x136c9856u, 0x646ba8c0u, 0xfd62f97au, 0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u, + 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u, 0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu, + 0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u, 0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u, + 0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u, 0xcfba9599u, 0xb8bda50fu, + 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu, 0xb6662d3du, + 0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u, + 0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u, + 0x6b6b51f4u, 0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u, + 0x65b0d9c6u, 0x12b7e950u, 0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u, + 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u, 0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu, + 0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u, 0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u, + 0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u, 0x206f85b3u, 0xb966d409u, 0xce61e49fu, + 0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u, 0xb7bd5c3bu, 0xc0ba6cadu, + 0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u, 0x73dc1683u, + 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u, + 0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u, + 0xfed41b76u, 0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u, + 0xd6d6a3e8u, 0xa1d1937eu, 0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu, + 0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u, 0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u, + 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u, 0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu, + 0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u, 0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du, + 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu, 0x72076785u, 0x05005713u, + 0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u, 0x0bdbdf21u, + 0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u, + 0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u, + 0xa00ae278u, 0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu, + 0xaed16a4au, 0xd9d65adcu, 0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u, + 0xbdbdf21cu, 0xcabac28au, 0x53b39330u, 0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu, + 0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u, 0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du +}; + +static const unsigned lodepng_crc32_table1[256] = { + 0x00000000u, 0x191b3141u, 0x32366282u, 0x2b2d53c3u, 0x646cc504u, 0x7d77f445u, 0x565aa786u, 0x4f4196c7u, + 0xc8d98a08u, 0xd1c2bb49u, 0xfaefe88au, 0xe3f4d9cbu, 0xacb54f0cu, 0xb5ae7e4du, 0x9e832d8eu, 0x87981ccfu, + 0x4ac21251u, 0x53d92310u, 0x78f470d3u, 0x61ef4192u, 0x2eaed755u, 0x37b5e614u, 0x1c98b5d7u, 0x05838496u, + 0x821b9859u, 0x9b00a918u, 0xb02dfadbu, 0xa936cb9au, 0xe6775d5du, 0xff6c6c1cu, 0xd4413fdfu, 0xcd5a0e9eu, + 0x958424a2u, 0x8c9f15e3u, 0xa7b24620u, 0xbea97761u, 0xf1e8e1a6u, 0xe8f3d0e7u, 0xc3de8324u, 0xdac5b265u, + 0x5d5daeaau, 0x44469febu, 0x6f6bcc28u, 0x7670fd69u, 0x39316baeu, 0x202a5aefu, 0x0b07092cu, 0x121c386du, + 0xdf4636f3u, 0xc65d07b2u, 0xed705471u, 0xf46b6530u, 0xbb2af3f7u, 0xa231c2b6u, 0x891c9175u, 0x9007a034u, + 0x179fbcfbu, 0x0e848dbau, 0x25a9de79u, 0x3cb2ef38u, 0x73f379ffu, 0x6ae848beu, 0x41c51b7du, 0x58de2a3cu, + 0xf0794f05u, 0xe9627e44u, 0xc24f2d87u, 0xdb541cc6u, 0x94158a01u, 0x8d0ebb40u, 0xa623e883u, 0xbf38d9c2u, + 0x38a0c50du, 0x21bbf44cu, 0x0a96a78fu, 0x138d96ceu, 0x5ccc0009u, 0x45d73148u, 0x6efa628bu, 0x77e153cau, + 0xbabb5d54u, 0xa3a06c15u, 0x888d3fd6u, 0x91960e97u, 0xded79850u, 0xc7cca911u, 0xece1fad2u, 0xf5facb93u, + 0x7262d75cu, 0x6b79e61du, 0x4054b5deu, 0x594f849fu, 0x160e1258u, 0x0f152319u, 0x243870dau, 0x3d23419bu, + 0x65fd6ba7u, 0x7ce65ae6u, 0x57cb0925u, 0x4ed03864u, 0x0191aea3u, 0x188a9fe2u, 0x33a7cc21u, 0x2abcfd60u, + 0xad24e1afu, 0xb43fd0eeu, 0x9f12832du, 0x8609b26cu, 0xc94824abu, 0xd05315eau, 0xfb7e4629u, 0xe2657768u, + 0x2f3f79f6u, 0x362448b7u, 0x1d091b74u, 0x04122a35u, 0x4b53bcf2u, 0x52488db3u, 0x7965de70u, 0x607eef31u, + 0xe7e6f3feu, 0xfefdc2bfu, 0xd5d0917cu, 0xcccba03du, 0x838a36fau, 0x9a9107bbu, 0xb1bc5478u, 0xa8a76539u, + 0x3b83984bu, 0x2298a90au, 0x09b5fac9u, 0x10aecb88u, 0x5fef5d4fu, 0x46f46c0eu, 0x6dd93fcdu, 0x74c20e8cu, + 0xf35a1243u, 0xea412302u, 0xc16c70c1u, 0xd8774180u, 0x9736d747u, 0x8e2de606u, 0xa500b5c5u, 0xbc1b8484u, + 0x71418a1au, 0x685abb5bu, 0x4377e898u, 0x5a6cd9d9u, 0x152d4f1eu, 0x0c367e5fu, 0x271b2d9cu, 0x3e001cddu, + 0xb9980012u, 0xa0833153u, 0x8bae6290u, 0x92b553d1u, 0xddf4c516u, 0xc4eff457u, 0xefc2a794u, 0xf6d996d5u, + 0xae07bce9u, 0xb71c8da8u, 0x9c31de6bu, 0x852aef2au, 0xca6b79edu, 0xd37048acu, 0xf85d1b6fu, 0xe1462a2eu, + 0x66de36e1u, 0x7fc507a0u, 0x54e85463u, 0x4df36522u, 0x02b2f3e5u, 0x1ba9c2a4u, 0x30849167u, 0x299fa026u, + 0xe4c5aeb8u, 0xfdde9ff9u, 0xd6f3cc3au, 0xcfe8fd7bu, 0x80a96bbcu, 0x99b25afdu, 0xb29f093eu, 0xab84387fu, + 0x2c1c24b0u, 0x350715f1u, 0x1e2a4632u, 0x07317773u, 0x4870e1b4u, 0x516bd0f5u, 0x7a468336u, 0x635db277u, + 0xcbfad74eu, 0xd2e1e60fu, 0xf9ccb5ccu, 0xe0d7848du, 0xaf96124au, 0xb68d230bu, 0x9da070c8u, 0x84bb4189u, + 0x03235d46u, 0x1a386c07u, 0x31153fc4u, 0x280e0e85u, 0x674f9842u, 0x7e54a903u, 0x5579fac0u, 0x4c62cb81u, + 0x8138c51fu, 0x9823f45eu, 0xb30ea79du, 0xaa1596dcu, 0xe554001bu, 0xfc4f315au, 0xd7626299u, 0xce7953d8u, + 0x49e14f17u, 0x50fa7e56u, 0x7bd72d95u, 0x62cc1cd4u, 0x2d8d8a13u, 0x3496bb52u, 0x1fbbe891u, 0x06a0d9d0u, + 0x5e7ef3ecu, 0x4765c2adu, 0x6c48916eu, 0x7553a02fu, 0x3a1236e8u, 0x230907a9u, 0x0824546au, 0x113f652bu, + 0x96a779e4u, 0x8fbc48a5u, 0xa4911b66u, 0xbd8a2a27u, 0xf2cbbce0u, 0xebd08da1u, 0xc0fdde62u, 0xd9e6ef23u, + 0x14bce1bdu, 0x0da7d0fcu, 0x268a833fu, 0x3f91b27eu, 0x70d024b9u, 0x69cb15f8u, 0x42e6463bu, 0x5bfd777au, + 0xdc656bb5u, 0xc57e5af4u, 0xee530937u, 0xf7483876u, 0xb809aeb1u, 0xa1129ff0u, 0x8a3fcc33u, 0x9324fd72u +}; + +static const unsigned lodepng_crc32_table2[256] = { + 0x00000000u, 0x01c26a37u, 0x0384d46eu, 0x0246be59u, 0x0709a8dcu, 0x06cbc2ebu, 0x048d7cb2u, 0x054f1685u, + 0x0e1351b8u, 0x0fd13b8fu, 0x0d9785d6u, 0x0c55efe1u, 0x091af964u, 0x08d89353u, 0x0a9e2d0au, 0x0b5c473du, + 0x1c26a370u, 0x1de4c947u, 0x1fa2771eu, 0x1e601d29u, 0x1b2f0bacu, 0x1aed619bu, 0x18abdfc2u, 0x1969b5f5u, + 0x1235f2c8u, 0x13f798ffu, 0x11b126a6u, 0x10734c91u, 0x153c5a14u, 0x14fe3023u, 0x16b88e7au, 0x177ae44du, + 0x384d46e0u, 0x398f2cd7u, 0x3bc9928eu, 0x3a0bf8b9u, 0x3f44ee3cu, 0x3e86840bu, 0x3cc03a52u, 0x3d025065u, + 0x365e1758u, 0x379c7d6fu, 0x35dac336u, 0x3418a901u, 0x3157bf84u, 0x3095d5b3u, 0x32d36beau, 0x331101ddu, + 0x246be590u, 0x25a98fa7u, 0x27ef31feu, 0x262d5bc9u, 0x23624d4cu, 0x22a0277bu, 0x20e69922u, 0x2124f315u, + 0x2a78b428u, 0x2bbade1fu, 0x29fc6046u, 0x283e0a71u, 0x2d711cf4u, 0x2cb376c3u, 0x2ef5c89au, 0x2f37a2adu, + 0x709a8dc0u, 0x7158e7f7u, 0x731e59aeu, 0x72dc3399u, 0x7793251cu, 0x76514f2bu, 0x7417f172u, 0x75d59b45u, + 0x7e89dc78u, 0x7f4bb64fu, 0x7d0d0816u, 0x7ccf6221u, 0x798074a4u, 0x78421e93u, 0x7a04a0cau, 0x7bc6cafdu, + 0x6cbc2eb0u, 0x6d7e4487u, 0x6f38fadeu, 0x6efa90e9u, 0x6bb5866cu, 0x6a77ec5bu, 0x68315202u, 0x69f33835u, + 0x62af7f08u, 0x636d153fu, 0x612bab66u, 0x60e9c151u, 0x65a6d7d4u, 0x6464bde3u, 0x662203bau, 0x67e0698du, + 0x48d7cb20u, 0x4915a117u, 0x4b531f4eu, 0x4a917579u, 0x4fde63fcu, 0x4e1c09cbu, 0x4c5ab792u, 0x4d98dda5u, + 0x46c49a98u, 0x4706f0afu, 0x45404ef6u, 0x448224c1u, 0x41cd3244u, 0x400f5873u, 0x4249e62au, 0x438b8c1du, + 0x54f16850u, 0x55330267u, 0x5775bc3eu, 0x56b7d609u, 0x53f8c08cu, 0x523aaabbu, 0x507c14e2u, 0x51be7ed5u, + 0x5ae239e8u, 0x5b2053dfu, 0x5966ed86u, 0x58a487b1u, 0x5deb9134u, 0x5c29fb03u, 0x5e6f455au, 0x5fad2f6du, + 0xe1351b80u, 0xe0f771b7u, 0xe2b1cfeeu, 0xe373a5d9u, 0xe63cb35cu, 0xe7fed96bu, 0xe5b86732u, 0xe47a0d05u, + 0xef264a38u, 0xeee4200fu, 0xeca29e56u, 0xed60f461u, 0xe82fe2e4u, 0xe9ed88d3u, 0xebab368au, 0xea695cbdu, + 0xfd13b8f0u, 0xfcd1d2c7u, 0xfe976c9eu, 0xff5506a9u, 0xfa1a102cu, 0xfbd87a1bu, 0xf99ec442u, 0xf85cae75u, + 0xf300e948u, 0xf2c2837fu, 0xf0843d26u, 0xf1465711u, 0xf4094194u, 0xf5cb2ba3u, 0xf78d95fau, 0xf64fffcdu, + 0xd9785d60u, 0xd8ba3757u, 0xdafc890eu, 0xdb3ee339u, 0xde71f5bcu, 0xdfb39f8bu, 0xddf521d2u, 0xdc374be5u, + 0xd76b0cd8u, 0xd6a966efu, 0xd4efd8b6u, 0xd52db281u, 0xd062a404u, 0xd1a0ce33u, 0xd3e6706au, 0xd2241a5du, + 0xc55efe10u, 0xc49c9427u, 0xc6da2a7eu, 0xc7184049u, 0xc25756ccu, 0xc3953cfbu, 0xc1d382a2u, 0xc011e895u, + 0xcb4dafa8u, 0xca8fc59fu, 0xc8c97bc6u, 0xc90b11f1u, 0xcc440774u, 0xcd866d43u, 0xcfc0d31au, 0xce02b92du, + 0x91af9640u, 0x906dfc77u, 0x922b422eu, 0x93e92819u, 0x96a63e9cu, 0x976454abu, 0x9522eaf2u, 0x94e080c5u, + 0x9fbcc7f8u, 0x9e7eadcfu, 0x9c381396u, 0x9dfa79a1u, 0x98b56f24u, 0x99770513u, 0x9b31bb4au, 0x9af3d17du, + 0x8d893530u, 0x8c4b5f07u, 0x8e0de15eu, 0x8fcf8b69u, 0x8a809decu, 0x8b42f7dbu, 0x89044982u, 0x88c623b5u, + 0x839a6488u, 0x82580ebfu, 0x801eb0e6u, 0x81dcdad1u, 0x8493cc54u, 0x8551a663u, 0x8717183au, 0x86d5720du, + 0xa9e2d0a0u, 0xa820ba97u, 0xaa6604ceu, 0xaba46ef9u, 0xaeeb787cu, 0xaf29124bu, 0xad6fac12u, 0xacadc625u, + 0xa7f18118u, 0xa633eb2fu, 0xa4755576u, 0xa5b73f41u, 0xa0f829c4u, 0xa13a43f3u, 0xa37cfdaau, 0xa2be979du, + 0xb5c473d0u, 0xb40619e7u, 0xb640a7beu, 0xb782cd89u, 0xb2cddb0cu, 0xb30fb13bu, 0xb1490f62u, 0xb08b6555u, + 0xbbd72268u, 0xba15485fu, 0xb853f606u, 0xb9919c31u, 0xbcde8ab4u, 0xbd1ce083u, 0xbf5a5edau, 0xbe9834edu +}; + +static const unsigned lodepng_crc32_table3[256] = { + 0x00000000u, 0xb8bc6765u, 0xaa09c88bu, 0x12b5afeeu, 0x8f629757u, 0x37def032u, 0x256b5fdcu, 0x9dd738b9u, + 0xc5b428efu, 0x7d084f8au, 0x6fbde064u, 0xd7018701u, 0x4ad6bfb8u, 0xf26ad8ddu, 0xe0df7733u, 0x58631056u, + 0x5019579fu, 0xe8a530fau, 0xfa109f14u, 0x42acf871u, 0xdf7bc0c8u, 0x67c7a7adu, 0x75720843u, 0xcdce6f26u, + 0x95ad7f70u, 0x2d111815u, 0x3fa4b7fbu, 0x8718d09eu, 0x1acfe827u, 0xa2738f42u, 0xb0c620acu, 0x087a47c9u, + 0xa032af3eu, 0x188ec85bu, 0x0a3b67b5u, 0xb28700d0u, 0x2f503869u, 0x97ec5f0cu, 0x8559f0e2u, 0x3de59787u, + 0x658687d1u, 0xdd3ae0b4u, 0xcf8f4f5au, 0x7733283fu, 0xeae41086u, 0x525877e3u, 0x40edd80du, 0xf851bf68u, + 0xf02bf8a1u, 0x48979fc4u, 0x5a22302au, 0xe29e574fu, 0x7f496ff6u, 0xc7f50893u, 0xd540a77du, 0x6dfcc018u, + 0x359fd04eu, 0x8d23b72bu, 0x9f9618c5u, 0x272a7fa0u, 0xbafd4719u, 0x0241207cu, 0x10f48f92u, 0xa848e8f7u, + 0x9b14583du, 0x23a83f58u, 0x311d90b6u, 0x89a1f7d3u, 0x1476cf6au, 0xaccaa80fu, 0xbe7f07e1u, 0x06c36084u, + 0x5ea070d2u, 0xe61c17b7u, 0xf4a9b859u, 0x4c15df3cu, 0xd1c2e785u, 0x697e80e0u, 0x7bcb2f0eu, 0xc377486bu, + 0xcb0d0fa2u, 0x73b168c7u, 0x6104c729u, 0xd9b8a04cu, 0x446f98f5u, 0xfcd3ff90u, 0xee66507eu, 0x56da371bu, + 0x0eb9274du, 0xb6054028u, 0xa4b0efc6u, 0x1c0c88a3u, 0x81dbb01au, 0x3967d77fu, 0x2bd27891u, 0x936e1ff4u, + 0x3b26f703u, 0x839a9066u, 0x912f3f88u, 0x299358edu, 0xb4446054u, 0x0cf80731u, 0x1e4da8dfu, 0xa6f1cfbau, + 0xfe92dfecu, 0x462eb889u, 0x549b1767u, 0xec277002u, 0x71f048bbu, 0xc94c2fdeu, 0xdbf98030u, 0x6345e755u, + 0x6b3fa09cu, 0xd383c7f9u, 0xc1366817u, 0x798a0f72u, 0xe45d37cbu, 0x5ce150aeu, 0x4e54ff40u, 0xf6e89825u, + 0xae8b8873u, 0x1637ef16u, 0x048240f8u, 0xbc3e279du, 0x21e91f24u, 0x99557841u, 0x8be0d7afu, 0x335cb0cau, + 0xed59b63bu, 0x55e5d15eu, 0x47507eb0u, 0xffec19d5u, 0x623b216cu, 0xda874609u, 0xc832e9e7u, 0x708e8e82u, + 0x28ed9ed4u, 0x9051f9b1u, 0x82e4565fu, 0x3a58313au, 0xa78f0983u, 0x1f336ee6u, 0x0d86c108u, 0xb53aa66du, + 0xbd40e1a4u, 0x05fc86c1u, 0x1749292fu, 0xaff54e4au, 0x322276f3u, 0x8a9e1196u, 0x982bbe78u, 0x2097d91du, + 0x78f4c94bu, 0xc048ae2eu, 0xd2fd01c0u, 0x6a4166a5u, 0xf7965e1cu, 0x4f2a3979u, 0x5d9f9697u, 0xe523f1f2u, + 0x4d6b1905u, 0xf5d77e60u, 0xe762d18eu, 0x5fdeb6ebu, 0xc2098e52u, 0x7ab5e937u, 0x680046d9u, 0xd0bc21bcu, + 0x88df31eau, 0x3063568fu, 0x22d6f961u, 0x9a6a9e04u, 0x07bda6bdu, 0xbf01c1d8u, 0xadb46e36u, 0x15080953u, + 0x1d724e9au, 0xa5ce29ffu, 0xb77b8611u, 0x0fc7e174u, 0x9210d9cdu, 0x2aacbea8u, 0x38191146u, 0x80a57623u, + 0xd8c66675u, 0x607a0110u, 0x72cfaefeu, 0xca73c99bu, 0x57a4f122u, 0xef189647u, 0xfdad39a9u, 0x45115eccu, + 0x764dee06u, 0xcef18963u, 0xdc44268du, 0x64f841e8u, 0xf92f7951u, 0x41931e34u, 0x5326b1dau, 0xeb9ad6bfu, + 0xb3f9c6e9u, 0x0b45a18cu, 0x19f00e62u, 0xa14c6907u, 0x3c9b51beu, 0x842736dbu, 0x96929935u, 0x2e2efe50u, + 0x2654b999u, 0x9ee8defcu, 0x8c5d7112u, 0x34e11677u, 0xa9362eceu, 0x118a49abu, 0x033fe645u, 0xbb838120u, + 0xe3e09176u, 0x5b5cf613u, 0x49e959fdu, 0xf1553e98u, 0x6c820621u, 0xd43e6144u, 0xc68bceaau, 0x7e37a9cfu, + 0xd67f4138u, 0x6ec3265du, 0x7c7689b3u, 0xc4caeed6u, 0x591dd66fu, 0xe1a1b10au, 0xf3141ee4u, 0x4ba87981u, + 0x13cb69d7u, 0xab770eb2u, 0xb9c2a15cu, 0x017ec639u, 0x9ca9fe80u, 0x241599e5u, 0x36a0360bu, 0x8e1c516eu, + 0x866616a7u, 0x3eda71c2u, 0x2c6fde2cu, 0x94d3b949u, 0x090481f0u, 0xb1b8e695u, 0xa30d497bu, 0x1bb12e1eu, + 0x43d23e48u, 0xfb6e592du, 0xe9dbf6c3u, 0x516791a6u, 0xccb0a91fu, 0x740cce7au, 0x66b96194u, 0xde0506f1u +}; + +static const unsigned lodepng_crc32_table4[256] = { + 0x00000000u, 0x3d6029b0u, 0x7ac05360u, 0x47a07ad0u, 0xf580a6c0u, 0xc8e08f70u, 0x8f40f5a0u, 0xb220dc10u, + 0x30704bc1u, 0x0d106271u, 0x4ab018a1u, 0x77d03111u, 0xc5f0ed01u, 0xf890c4b1u, 0xbf30be61u, 0x825097d1u, + 0x60e09782u, 0x5d80be32u, 0x1a20c4e2u, 0x2740ed52u, 0x95603142u, 0xa80018f2u, 0xefa06222u, 0xd2c04b92u, + 0x5090dc43u, 0x6df0f5f3u, 0x2a508f23u, 0x1730a693u, 0xa5107a83u, 0x98705333u, 0xdfd029e3u, 0xe2b00053u, + 0xc1c12f04u, 0xfca106b4u, 0xbb017c64u, 0x866155d4u, 0x344189c4u, 0x0921a074u, 0x4e81daa4u, 0x73e1f314u, + 0xf1b164c5u, 0xccd14d75u, 0x8b7137a5u, 0xb6111e15u, 0x0431c205u, 0x3951ebb5u, 0x7ef19165u, 0x4391b8d5u, + 0xa121b886u, 0x9c419136u, 0xdbe1ebe6u, 0xe681c256u, 0x54a11e46u, 0x69c137f6u, 0x2e614d26u, 0x13016496u, + 0x9151f347u, 0xac31daf7u, 0xeb91a027u, 0xd6f18997u, 0x64d15587u, 0x59b17c37u, 0x1e1106e7u, 0x23712f57u, + 0x58f35849u, 0x659371f9u, 0x22330b29u, 0x1f532299u, 0xad73fe89u, 0x9013d739u, 0xd7b3ade9u, 0xead38459u, + 0x68831388u, 0x55e33a38u, 0x124340e8u, 0x2f236958u, 0x9d03b548u, 0xa0639cf8u, 0xe7c3e628u, 0xdaa3cf98u, + 0x3813cfcbu, 0x0573e67bu, 0x42d39cabu, 0x7fb3b51bu, 0xcd93690bu, 0xf0f340bbu, 0xb7533a6bu, 0x8a3313dbu, + 0x0863840au, 0x3503adbau, 0x72a3d76au, 0x4fc3fedau, 0xfde322cau, 0xc0830b7au, 0x872371aau, 0xba43581au, + 0x9932774du, 0xa4525efdu, 0xe3f2242du, 0xde920d9du, 0x6cb2d18du, 0x51d2f83du, 0x167282edu, 0x2b12ab5du, + 0xa9423c8cu, 0x9422153cu, 0xd3826fecu, 0xeee2465cu, 0x5cc29a4cu, 0x61a2b3fcu, 0x2602c92cu, 0x1b62e09cu, + 0xf9d2e0cfu, 0xc4b2c97fu, 0x8312b3afu, 0xbe729a1fu, 0x0c52460fu, 0x31326fbfu, 0x7692156fu, 0x4bf23cdfu, + 0xc9a2ab0eu, 0xf4c282beu, 0xb362f86eu, 0x8e02d1deu, 0x3c220dceu, 0x0142247eu, 0x46e25eaeu, 0x7b82771eu, + 0xb1e6b092u, 0x8c869922u, 0xcb26e3f2u, 0xf646ca42u, 0x44661652u, 0x79063fe2u, 0x3ea64532u, 0x03c66c82u, + 0x8196fb53u, 0xbcf6d2e3u, 0xfb56a833u, 0xc6368183u, 0x74165d93u, 0x49767423u, 0x0ed60ef3u, 0x33b62743u, + 0xd1062710u, 0xec660ea0u, 0xabc67470u, 0x96a65dc0u, 0x248681d0u, 0x19e6a860u, 0x5e46d2b0u, 0x6326fb00u, + 0xe1766cd1u, 0xdc164561u, 0x9bb63fb1u, 0xa6d61601u, 0x14f6ca11u, 0x2996e3a1u, 0x6e369971u, 0x5356b0c1u, + 0x70279f96u, 0x4d47b626u, 0x0ae7ccf6u, 0x3787e546u, 0x85a73956u, 0xb8c710e6u, 0xff676a36u, 0xc2074386u, + 0x4057d457u, 0x7d37fde7u, 0x3a978737u, 0x07f7ae87u, 0xb5d77297u, 0x88b75b27u, 0xcf1721f7u, 0xf2770847u, + 0x10c70814u, 0x2da721a4u, 0x6a075b74u, 0x576772c4u, 0xe547aed4u, 0xd8278764u, 0x9f87fdb4u, 0xa2e7d404u, + 0x20b743d5u, 0x1dd76a65u, 0x5a7710b5u, 0x67173905u, 0xd537e515u, 0xe857cca5u, 0xaff7b675u, 0x92979fc5u, + 0xe915e8dbu, 0xd475c16bu, 0x93d5bbbbu, 0xaeb5920bu, 0x1c954e1bu, 0x21f567abu, 0x66551d7bu, 0x5b3534cbu, + 0xd965a31au, 0xe4058aaau, 0xa3a5f07au, 0x9ec5d9cau, 0x2ce505dau, 0x11852c6au, 0x562556bau, 0x6b457f0au, + 0x89f57f59u, 0xb49556e9u, 0xf3352c39u, 0xce550589u, 0x7c75d999u, 0x4115f029u, 0x06b58af9u, 0x3bd5a349u, + 0xb9853498u, 0x84e51d28u, 0xc34567f8u, 0xfe254e48u, 0x4c059258u, 0x7165bbe8u, 0x36c5c138u, 0x0ba5e888u, + 0x28d4c7dfu, 0x15b4ee6fu, 0x521494bfu, 0x6f74bd0fu, 0xdd54611fu, 0xe03448afu, 0xa794327fu, 0x9af41bcfu, + 0x18a48c1eu, 0x25c4a5aeu, 0x6264df7eu, 0x5f04f6ceu, 0xed242adeu, 0xd044036eu, 0x97e479beu, 0xaa84500eu, + 0x4834505du, 0x755479edu, 0x32f4033du, 0x0f942a8du, 0xbdb4f69du, 0x80d4df2du, 0xc774a5fdu, 0xfa148c4du, + 0x78441b9cu, 0x4524322cu, 0x028448fcu, 0x3fe4614cu, 0x8dc4bd5cu, 0xb0a494ecu, 0xf704ee3cu, 0xca64c78cu +}; + +static const unsigned lodepng_crc32_table5[256] = { + 0x00000000u, 0xcb5cd3a5u, 0x4dc8a10bu, 0x869472aeu, 0x9b914216u, 0x50cd91b3u, 0xd659e31du, 0x1d0530b8u, + 0xec53826du, 0x270f51c8u, 0xa19b2366u, 0x6ac7f0c3u, 0x77c2c07bu, 0xbc9e13deu, 0x3a0a6170u, 0xf156b2d5u, + 0x03d6029bu, 0xc88ad13eu, 0x4e1ea390u, 0x85427035u, 0x9847408du, 0x531b9328u, 0xd58fe186u, 0x1ed33223u, + 0xef8580f6u, 0x24d95353u, 0xa24d21fdu, 0x6911f258u, 0x7414c2e0u, 0xbf481145u, 0x39dc63ebu, 0xf280b04eu, + 0x07ac0536u, 0xccf0d693u, 0x4a64a43du, 0x81387798u, 0x9c3d4720u, 0x57619485u, 0xd1f5e62bu, 0x1aa9358eu, + 0xebff875bu, 0x20a354feu, 0xa6372650u, 0x6d6bf5f5u, 0x706ec54du, 0xbb3216e8u, 0x3da66446u, 0xf6fab7e3u, + 0x047a07adu, 0xcf26d408u, 0x49b2a6a6u, 0x82ee7503u, 0x9feb45bbu, 0x54b7961eu, 0xd223e4b0u, 0x197f3715u, + 0xe82985c0u, 0x23755665u, 0xa5e124cbu, 0x6ebdf76eu, 0x73b8c7d6u, 0xb8e41473u, 0x3e7066ddu, 0xf52cb578u, + 0x0f580a6cu, 0xc404d9c9u, 0x4290ab67u, 0x89cc78c2u, 0x94c9487au, 0x5f959bdfu, 0xd901e971u, 0x125d3ad4u, + 0xe30b8801u, 0x28575ba4u, 0xaec3290au, 0x659ffaafu, 0x789aca17u, 0xb3c619b2u, 0x35526b1cu, 0xfe0eb8b9u, + 0x0c8e08f7u, 0xc7d2db52u, 0x4146a9fcu, 0x8a1a7a59u, 0x971f4ae1u, 0x5c439944u, 0xdad7ebeau, 0x118b384fu, + 0xe0dd8a9au, 0x2b81593fu, 0xad152b91u, 0x6649f834u, 0x7b4cc88cu, 0xb0101b29u, 0x36846987u, 0xfdd8ba22u, + 0x08f40f5au, 0xc3a8dcffu, 0x453cae51u, 0x8e607df4u, 0x93654d4cu, 0x58399ee9u, 0xdeadec47u, 0x15f13fe2u, + 0xe4a78d37u, 0x2ffb5e92u, 0xa96f2c3cu, 0x6233ff99u, 0x7f36cf21u, 0xb46a1c84u, 0x32fe6e2au, 0xf9a2bd8fu, + 0x0b220dc1u, 0xc07ede64u, 0x46eaaccau, 0x8db67f6fu, 0x90b34fd7u, 0x5bef9c72u, 0xdd7beedcu, 0x16273d79u, + 0xe7718facu, 0x2c2d5c09u, 0xaab92ea7u, 0x61e5fd02u, 0x7ce0cdbau, 0xb7bc1e1fu, 0x31286cb1u, 0xfa74bf14u, + 0x1eb014d8u, 0xd5ecc77du, 0x5378b5d3u, 0x98246676u, 0x852156ceu, 0x4e7d856bu, 0xc8e9f7c5u, 0x03b52460u, + 0xf2e396b5u, 0x39bf4510u, 0xbf2b37beu, 0x7477e41bu, 0x6972d4a3u, 0xa22e0706u, 0x24ba75a8u, 0xefe6a60du, + 0x1d661643u, 0xd63ac5e6u, 0x50aeb748u, 0x9bf264edu, 0x86f75455u, 0x4dab87f0u, 0xcb3ff55eu, 0x006326fbu, + 0xf135942eu, 0x3a69478bu, 0xbcfd3525u, 0x77a1e680u, 0x6aa4d638u, 0xa1f8059du, 0x276c7733u, 0xec30a496u, + 0x191c11eeu, 0xd240c24bu, 0x54d4b0e5u, 0x9f886340u, 0x828d53f8u, 0x49d1805du, 0xcf45f2f3u, 0x04192156u, + 0xf54f9383u, 0x3e134026u, 0xb8873288u, 0x73dbe12du, 0x6eded195u, 0xa5820230u, 0x2316709eu, 0xe84aa33bu, + 0x1aca1375u, 0xd196c0d0u, 0x5702b27eu, 0x9c5e61dbu, 0x815b5163u, 0x4a0782c6u, 0xcc93f068u, 0x07cf23cdu, + 0xf6999118u, 0x3dc542bdu, 0xbb513013u, 0x700de3b6u, 0x6d08d30eu, 0xa65400abu, 0x20c07205u, 0xeb9ca1a0u, + 0x11e81eb4u, 0xdab4cd11u, 0x5c20bfbfu, 0x977c6c1au, 0x8a795ca2u, 0x41258f07u, 0xc7b1fda9u, 0x0ced2e0cu, + 0xfdbb9cd9u, 0x36e74f7cu, 0xb0733dd2u, 0x7b2fee77u, 0x662adecfu, 0xad760d6au, 0x2be27fc4u, 0xe0beac61u, + 0x123e1c2fu, 0xd962cf8au, 0x5ff6bd24u, 0x94aa6e81u, 0x89af5e39u, 0x42f38d9cu, 0xc467ff32u, 0x0f3b2c97u, + 0xfe6d9e42u, 0x35314de7u, 0xb3a53f49u, 0x78f9ececu, 0x65fcdc54u, 0xaea00ff1u, 0x28347d5fu, 0xe368aefau, + 0x16441b82u, 0xdd18c827u, 0x5b8cba89u, 0x90d0692cu, 0x8dd55994u, 0x46898a31u, 0xc01df89fu, 0x0b412b3au, + 0xfa1799efu, 0x314b4a4au, 0xb7df38e4u, 0x7c83eb41u, 0x6186dbf9u, 0xaada085cu, 0x2c4e7af2u, 0xe712a957u, + 0x15921919u, 0xdececabcu, 0x585ab812u, 0x93066bb7u, 0x8e035b0fu, 0x455f88aau, 0xc3cbfa04u, 0x089729a1u, + 0xf9c19b74u, 0x329d48d1u, 0xb4093a7fu, 0x7f55e9dau, 0x6250d962u, 0xa90c0ac7u, 0x2f987869u, 0xe4c4abccu +}; + +static const unsigned lodepng_crc32_table6[256] = { + 0x00000000u, 0xa6770bb4u, 0x979f1129u, 0x31e81a9du, 0xf44f2413u, 0x52382fa7u, 0x63d0353au, 0xc5a73e8eu, + 0x33ef4e67u, 0x959845d3u, 0xa4705f4eu, 0x020754fau, 0xc7a06a74u, 0x61d761c0u, 0x503f7b5du, 0xf64870e9u, + 0x67de9cceu, 0xc1a9977au, 0xf0418de7u, 0x56368653u, 0x9391b8ddu, 0x35e6b369u, 0x040ea9f4u, 0xa279a240u, + 0x5431d2a9u, 0xf246d91du, 0xc3aec380u, 0x65d9c834u, 0xa07ef6bau, 0x0609fd0eu, 0x37e1e793u, 0x9196ec27u, + 0xcfbd399cu, 0x69ca3228u, 0x582228b5u, 0xfe552301u, 0x3bf21d8fu, 0x9d85163bu, 0xac6d0ca6u, 0x0a1a0712u, + 0xfc5277fbu, 0x5a257c4fu, 0x6bcd66d2u, 0xcdba6d66u, 0x081d53e8u, 0xae6a585cu, 0x9f8242c1u, 0x39f54975u, + 0xa863a552u, 0x0e14aee6u, 0x3ffcb47bu, 0x998bbfcfu, 0x5c2c8141u, 0xfa5b8af5u, 0xcbb39068u, 0x6dc49bdcu, + 0x9b8ceb35u, 0x3dfbe081u, 0x0c13fa1cu, 0xaa64f1a8u, 0x6fc3cf26u, 0xc9b4c492u, 0xf85cde0fu, 0x5e2bd5bbu, + 0x440b7579u, 0xe27c7ecdu, 0xd3946450u, 0x75e36fe4u, 0xb044516au, 0x16335adeu, 0x27db4043u, 0x81ac4bf7u, + 0x77e43b1eu, 0xd19330aau, 0xe07b2a37u, 0x460c2183u, 0x83ab1f0du, 0x25dc14b9u, 0x14340e24u, 0xb2430590u, + 0x23d5e9b7u, 0x85a2e203u, 0xb44af89eu, 0x123df32au, 0xd79acda4u, 0x71edc610u, 0x4005dc8du, 0xe672d739u, + 0x103aa7d0u, 0xb64dac64u, 0x87a5b6f9u, 0x21d2bd4du, 0xe47583c3u, 0x42028877u, 0x73ea92eau, 0xd59d995eu, + 0x8bb64ce5u, 0x2dc14751u, 0x1c295dccu, 0xba5e5678u, 0x7ff968f6u, 0xd98e6342u, 0xe86679dfu, 0x4e11726bu, + 0xb8590282u, 0x1e2e0936u, 0x2fc613abu, 0x89b1181fu, 0x4c162691u, 0xea612d25u, 0xdb8937b8u, 0x7dfe3c0cu, + 0xec68d02bu, 0x4a1fdb9fu, 0x7bf7c102u, 0xdd80cab6u, 0x1827f438u, 0xbe50ff8cu, 0x8fb8e511u, 0x29cfeea5u, + 0xdf879e4cu, 0x79f095f8u, 0x48188f65u, 0xee6f84d1u, 0x2bc8ba5fu, 0x8dbfb1ebu, 0xbc57ab76u, 0x1a20a0c2u, + 0x8816eaf2u, 0x2e61e146u, 0x1f89fbdbu, 0xb9fef06fu, 0x7c59cee1u, 0xda2ec555u, 0xebc6dfc8u, 0x4db1d47cu, + 0xbbf9a495u, 0x1d8eaf21u, 0x2c66b5bcu, 0x8a11be08u, 0x4fb68086u, 0xe9c18b32u, 0xd82991afu, 0x7e5e9a1bu, + 0xefc8763cu, 0x49bf7d88u, 0x78576715u, 0xde206ca1u, 0x1b87522fu, 0xbdf0599bu, 0x8c184306u, 0x2a6f48b2u, + 0xdc27385bu, 0x7a5033efu, 0x4bb82972u, 0xedcf22c6u, 0x28681c48u, 0x8e1f17fcu, 0xbff70d61u, 0x198006d5u, + 0x47abd36eu, 0xe1dcd8dau, 0xd034c247u, 0x7643c9f3u, 0xb3e4f77du, 0x1593fcc9u, 0x247be654u, 0x820cede0u, + 0x74449d09u, 0xd23396bdu, 0xe3db8c20u, 0x45ac8794u, 0x800bb91au, 0x267cb2aeu, 0x1794a833u, 0xb1e3a387u, + 0x20754fa0u, 0x86024414u, 0xb7ea5e89u, 0x119d553du, 0xd43a6bb3u, 0x724d6007u, 0x43a57a9au, 0xe5d2712eu, + 0x139a01c7u, 0xb5ed0a73u, 0x840510eeu, 0x22721b5au, 0xe7d525d4u, 0x41a22e60u, 0x704a34fdu, 0xd63d3f49u, + 0xcc1d9f8bu, 0x6a6a943fu, 0x5b828ea2u, 0xfdf58516u, 0x3852bb98u, 0x9e25b02cu, 0xafcdaab1u, 0x09baa105u, + 0xfff2d1ecu, 0x5985da58u, 0x686dc0c5u, 0xce1acb71u, 0x0bbdf5ffu, 0xadcafe4bu, 0x9c22e4d6u, 0x3a55ef62u, + 0xabc30345u, 0x0db408f1u, 0x3c5c126cu, 0x9a2b19d8u, 0x5f8c2756u, 0xf9fb2ce2u, 0xc813367fu, 0x6e643dcbu, + 0x982c4d22u, 0x3e5b4696u, 0x0fb35c0bu, 0xa9c457bfu, 0x6c636931u, 0xca146285u, 0xfbfc7818u, 0x5d8b73acu, + 0x03a0a617u, 0xa5d7ada3u, 0x943fb73eu, 0x3248bc8au, 0xf7ef8204u, 0x519889b0u, 0x6070932du, 0xc6079899u, + 0x304fe870u, 0x9638e3c4u, 0xa7d0f959u, 0x01a7f2edu, 0xc400cc63u, 0x6277c7d7u, 0x539fdd4au, 0xf5e8d6feu, + 0x647e3ad9u, 0xc209316du, 0xf3e12bf0u, 0x55962044u, 0x90311ecau, 0x3646157eu, 0x07ae0fe3u, 0xa1d90457u, + 0x579174beu, 0xf1e67f0au, 0xc00e6597u, 0x66796e23u, 0xa3de50adu, 0x05a95b19u, 0x34414184u, 0x92364a30u +}; + +static const unsigned lodepng_crc32_table7[256] = { + 0x00000000u, 0xccaa009eu, 0x4225077du, 0x8e8f07e3u, 0x844a0efau, 0x48e00e64u, 0xc66f0987u, 0x0ac50919u, + 0xd3e51bb5u, 0x1f4f1b2bu, 0x91c01cc8u, 0x5d6a1c56u, 0x57af154fu, 0x9b0515d1u, 0x158a1232u, 0xd92012acu, + 0x7cbb312bu, 0xb01131b5u, 0x3e9e3656u, 0xf23436c8u, 0xf8f13fd1u, 0x345b3f4fu, 0xbad438acu, 0x767e3832u, + 0xaf5e2a9eu, 0x63f42a00u, 0xed7b2de3u, 0x21d12d7du, 0x2b142464u, 0xe7be24fau, 0x69312319u, 0xa59b2387u, + 0xf9766256u, 0x35dc62c8u, 0xbb53652bu, 0x77f965b5u, 0x7d3c6cacu, 0xb1966c32u, 0x3f196bd1u, 0xf3b36b4fu, + 0x2a9379e3u, 0xe639797du, 0x68b67e9eu, 0xa41c7e00u, 0xaed97719u, 0x62737787u, 0xecfc7064u, 0x205670fau, + 0x85cd537du, 0x496753e3u, 0xc7e85400u, 0x0b42549eu, 0x01875d87u, 0xcd2d5d19u, 0x43a25afau, 0x8f085a64u, + 0x562848c8u, 0x9a824856u, 0x140d4fb5u, 0xd8a74f2bu, 0xd2624632u, 0x1ec846acu, 0x9047414fu, 0x5ced41d1u, + 0x299dc2edu, 0xe537c273u, 0x6bb8c590u, 0xa712c50eu, 0xadd7cc17u, 0x617dcc89u, 0xeff2cb6au, 0x2358cbf4u, + 0xfa78d958u, 0x36d2d9c6u, 0xb85dde25u, 0x74f7debbu, 0x7e32d7a2u, 0xb298d73cu, 0x3c17d0dfu, 0xf0bdd041u, + 0x5526f3c6u, 0x998cf358u, 0x1703f4bbu, 0xdba9f425u, 0xd16cfd3cu, 0x1dc6fda2u, 0x9349fa41u, 0x5fe3fadfu, + 0x86c3e873u, 0x4a69e8edu, 0xc4e6ef0eu, 0x084cef90u, 0x0289e689u, 0xce23e617u, 0x40ace1f4u, 0x8c06e16au, + 0xd0eba0bbu, 0x1c41a025u, 0x92cea7c6u, 0x5e64a758u, 0x54a1ae41u, 0x980baedfu, 0x1684a93cu, 0xda2ea9a2u, + 0x030ebb0eu, 0xcfa4bb90u, 0x412bbc73u, 0x8d81bcedu, 0x8744b5f4u, 0x4beeb56au, 0xc561b289u, 0x09cbb217u, + 0xac509190u, 0x60fa910eu, 0xee7596edu, 0x22df9673u, 0x281a9f6au, 0xe4b09ff4u, 0x6a3f9817u, 0xa6959889u, + 0x7fb58a25u, 0xb31f8abbu, 0x3d908d58u, 0xf13a8dc6u, 0xfbff84dfu, 0x37558441u, 0xb9da83a2u, 0x7570833cu, + 0x533b85dau, 0x9f918544u, 0x111e82a7u, 0xddb48239u, 0xd7718b20u, 0x1bdb8bbeu, 0x95548c5du, 0x59fe8cc3u, + 0x80de9e6fu, 0x4c749ef1u, 0xc2fb9912u, 0x0e51998cu, 0x04949095u, 0xc83e900bu, 0x46b197e8u, 0x8a1b9776u, + 0x2f80b4f1u, 0xe32ab46fu, 0x6da5b38cu, 0xa10fb312u, 0xabcaba0bu, 0x6760ba95u, 0xe9efbd76u, 0x2545bde8u, + 0xfc65af44u, 0x30cfafdau, 0xbe40a839u, 0x72eaa8a7u, 0x782fa1beu, 0xb485a120u, 0x3a0aa6c3u, 0xf6a0a65du, + 0xaa4de78cu, 0x66e7e712u, 0xe868e0f1u, 0x24c2e06fu, 0x2e07e976u, 0xe2ade9e8u, 0x6c22ee0bu, 0xa088ee95u, + 0x79a8fc39u, 0xb502fca7u, 0x3b8dfb44u, 0xf727fbdau, 0xfde2f2c3u, 0x3148f25du, 0xbfc7f5beu, 0x736df520u, + 0xd6f6d6a7u, 0x1a5cd639u, 0x94d3d1dau, 0x5879d144u, 0x52bcd85du, 0x9e16d8c3u, 0x1099df20u, 0xdc33dfbeu, + 0x0513cd12u, 0xc9b9cd8cu, 0x4736ca6fu, 0x8b9ccaf1u, 0x8159c3e8u, 0x4df3c376u, 0xc37cc495u, 0x0fd6c40bu, + 0x7aa64737u, 0xb60c47a9u, 0x3883404au, 0xf42940d4u, 0xfeec49cdu, 0x32464953u, 0xbcc94eb0u, 0x70634e2eu, + 0xa9435c82u, 0x65e95c1cu, 0xeb665bffu, 0x27cc5b61u, 0x2d095278u, 0xe1a352e6u, 0x6f2c5505u, 0xa386559bu, + 0x061d761cu, 0xcab77682u, 0x44387161u, 0x889271ffu, 0x825778e6u, 0x4efd7878u, 0xc0727f9bu, 0x0cd87f05u, + 0xd5f86da9u, 0x19526d37u, 0x97dd6ad4u, 0x5b776a4au, 0x51b26353u, 0x9d1863cdu, 0x1397642eu, 0xdf3d64b0u, + 0x83d02561u, 0x4f7a25ffu, 0xc1f5221cu, 0x0d5f2282u, 0x079a2b9bu, 0xcb302b05u, 0x45bf2ce6u, 0x89152c78u, + 0x50353ed4u, 0x9c9f3e4au, 0x121039a9u, 0xdeba3937u, 0xd47f302eu, 0x18d530b0u, 0x965a3753u, 0x5af037cdu, + 0xff6b144au, 0x33c114d4u, 0xbd4e1337u, 0x71e413a9u, 0x7b211ab0u, 0xb78b1a2eu, 0x39041dcdu, 0xf5ae1d53u, + 0x2c8e0fffu, 0xe0240f61u, 0x6eab0882u, 0xa201081cu, 0xa8c40105u, 0x646e019bu, 0xeae10678u, 0x264b06e6u +}; + +/* Computes the cyclic redundancy check as used by PNG chunks*/ +unsigned lodepng_crc32(const unsigned char* data, size_t length) { + /*Using the Slicing by Eight algorithm*/ + unsigned r = 0xffffffffu; + while(length >= 8) { + r = lodepng_crc32_table7[(data[0] ^ (r & 0xffu))] ^ + lodepng_crc32_table6[(data[1] ^ ((r >> 8) & 0xffu))] ^ + lodepng_crc32_table5[(data[2] ^ ((r >> 16) & 0xffu))] ^ + lodepng_crc32_table4[(data[3] ^ ((r >> 24) & 0xffu))] ^ + lodepng_crc32_table3[data[4]] ^ + lodepng_crc32_table2[data[5]] ^ + lodepng_crc32_table1[data[6]] ^ + lodepng_crc32_table0[data[7]]; + data += 8; + length -= 8; + } + while(length--) { + r = lodepng_crc32_table0[(r ^ *data++) & 0xffu] ^ (r >> 8); + } + return r ^ 0xffffffffu; +} +#else /* LODEPNG_COMPILE_CRC */ +/*in this case, the function is only declared here, and must be defined externally +so that it will be linked in. + +Example implementation that uses a much smaller lookup table for memory constrained cases: + +unsigned lodepng_crc32(const unsigned char* data, size_t length) { + unsigned r = 0xffffffffu; + static const unsigned table[16] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c + }; + while(length--) { + r = table[(r ^ *data) & 0xf] ^ (r >> 4); + r = table[(r ^ (*data >> 4)) & 0xf] ^ (r >> 4); + data++; + } + return r ^ 0xffffffffu; +} +*/ +unsigned lodepng_crc32(const unsigned char* data, size_t length); +#endif /* LODEPNG_COMPILE_CRC */ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Reading and writing PNG color channel bits / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/* The color channel bits of less-than-8-bit pixels are read with the MSB of bytes first, +so LodePNGBitWriter and LodePNGBitReader can't be used for those. */ + +static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) { + unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); + ++(*bitpointer); + return result; +} + +/* TODO: make this faster */ +static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) { + unsigned result = 0; + size_t i; + for(i = 0 ; i < nbits; ++i) { + result <<= 1u; + result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream); + } + return result; +} + +static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) { + /*the current bit in bitstream may be 0 or 1 for this to work*/ + if(bit == 0) bitstream[(*bitpointer) >> 3u] &= (unsigned char)(~(1u << (7u - ((*bitpointer) & 7u)))); + else bitstream[(*bitpointer) >> 3u] |= (1u << (7u - ((*bitpointer) & 7u))); + ++(*bitpointer); +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG chunks / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +unsigned lodepng_chunk_length(const unsigned char* chunk) { + return lodepng_read32bitInt(chunk); +} + +void lodepng_chunk_type(char type[5], const unsigned char* chunk) { + unsigned i; + for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i]; + type[4] = 0; /*null termination char*/ +} + +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type) { + if(lodepng_strlen(type) != 4) return 0; + return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]); +} + +unsigned char lodepng_chunk_ancillary(const unsigned char* chunk) { + return((chunk[4] & 32) != 0); +} + +unsigned char lodepng_chunk_private(const unsigned char* chunk) { + return((chunk[6] & 32) != 0); +} + +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk) { + return((chunk[7] & 32) != 0); +} + +unsigned char* lodepng_chunk_data(unsigned char* chunk) { + return &chunk[8]; +} + +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk) { + return &chunk[8]; +} + +unsigned lodepng_chunk_check_crc(const unsigned char* chunk) { + unsigned length = lodepng_chunk_length(chunk); + unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]); + /*the CRC is taken of the data and the 4 chunk type letters, not the length*/ + unsigned checksum = lodepng_crc32(&chunk[4], length + 4); + if(CRC != checksum) return 1; + else return 0; +} + +void lodepng_chunk_generate_crc(unsigned char* chunk) { + unsigned length = lodepng_chunk_length(chunk); + unsigned CRC = lodepng_crc32(&chunk[4], length + 4); + lodepng_set32bitInt(chunk + 8 + length, CRC); +} + +unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end) { + size_t available_size = (size_t)(end - chunk); + if(chunk >= end || available_size < 12) return end; /*too small to contain a chunk*/ + if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 + && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { + /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ + return chunk + 8; + } else { + size_t total_chunk_length; + if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end; + if(total_chunk_length > available_size) return end; /*outside of range*/ + return chunk + total_chunk_length; + } +} + +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end) { + size_t available_size = (size_t)(end - chunk); + if(chunk >= end || available_size < 12) return end; /*too small to contain a chunk*/ + if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 + && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { + /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ + return chunk + 8; + } else { + size_t total_chunk_length; + if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end; + if(total_chunk_length > available_size) return end; /*outside of range*/ + return chunk + total_chunk_length; + } +} + +unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]) { + for(;;) { + if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */ + if(lodepng_chunk_type_equals(chunk, type)) return chunk; + chunk = lodepng_chunk_next(chunk, end); + } +} + +const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) { + for(;;) { + if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */ + if(lodepng_chunk_type_equals(chunk, type)) return chunk; + chunk = lodepng_chunk_next_const(chunk, end); + } +} + +unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk) { + unsigned i; + size_t total_chunk_length, new_length; + unsigned char *chunk_start, *new_buffer; + + if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return 77; + if(lodepng_addofl(*outsize, total_chunk_length, &new_length)) return 77; + + new_buffer = (unsigned char*)lodepng_realloc(*out, new_length); + if(!new_buffer) return 83; /*alloc fail*/ + (*out) = new_buffer; + (*outsize) = new_length; + chunk_start = &(*out)[new_length - total_chunk_length]; + + for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i]; + + return 0; +} + +/*Sets length and name and allocates the space for data and crc but does not +set data or crc yet. Returns the start of the chunk in chunk. The start of +the data is at chunk + 8. To finalize chunk, add the data, then use +lodepng_chunk_generate_crc */ +static unsigned lodepng_chunk_init(unsigned char** chunk, + ucvector* out, + unsigned length, const char* type) { + size_t new_length = out->size; + if(lodepng_addofl(new_length, length, &new_length)) return 77; + if(lodepng_addofl(new_length, 12, &new_length)) return 77; + if(!ucvector_resize(out, new_length)) return 83; /*alloc fail*/ + *chunk = out->data + new_length - length - 12u; + + /*1: length*/ + lodepng_set32bitInt(*chunk, length); + + /*2: chunk name (4 letters)*/ + lodepng_memcpy(*chunk + 4, type, 4); + + return 0; +} + +/* like lodepng_chunk_create but with custom allocsize */ +static unsigned lodepng_chunk_createv(ucvector* out, + unsigned length, const char* type, const unsigned char* data) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, length, type)); + + /*3: the data*/ + lodepng_memcpy(chunk + 8, data, length); + + /*4: CRC (of the chunkname characters and the data)*/ + lodepng_chunk_generate_crc(chunk); + + return 0; +} + +unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, + unsigned length, const char* type, const unsigned char* data) { + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_chunk_createv(&v, length, type, data); + *out = v.data; + *outsize = v.size; + return error; +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Color types, channels, bits / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*checks if the colortype is valid and the bitdepth bd is allowed for this colortype. +Return value is a LodePNG error code.*/ +static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) { + switch(colortype) { + case LCT_GREY: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; + case LCT_RGB: if(!( bd == 8 || bd == 16)) return 37; break; + case LCT_PALETTE: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; + case LCT_GREY_ALPHA: if(!( bd == 8 || bd == 16)) return 37; break; + case LCT_RGBA: if(!( bd == 8 || bd == 16)) return 37; break; + case LCT_MAX_OCTET_VALUE: return 31; /* invalid color type */ + default: return 31; /* invalid color type */ + } + return 0; /*allowed color type / bits combination*/ +} + +static unsigned getNumColorChannels(LodePNGColorType colortype) { + switch(colortype) { + case LCT_GREY: return 1; + case LCT_RGB: return 3; + case LCT_PALETTE: return 1; + case LCT_GREY_ALPHA: return 2; + case LCT_RGBA: return 4; + case LCT_MAX_OCTET_VALUE: return 0; /* invalid color type */ + default: return 0; /*invalid color type*/ + } +} + +static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) { + /*bits per pixel is amount of channels * bits per channel*/ + return getNumColorChannels(colortype) * bitdepth; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +void lodepng_color_mode_init(LodePNGColorMode* info) { + info->key_defined = 0; + info->key_r = info->key_g = info->key_b = 0; + info->colortype = LCT_RGBA; + info->bitdepth = 8; + info->palette = 0; + info->palettesize = 0; +} + +/*allocates palette memory if needed, and initializes all colors to black*/ +static void lodepng_color_mode_alloc_palette(LodePNGColorMode* info) { + size_t i; + /*if the palette is already allocated, it will have size 1024 so no reallocation needed in that case*/ + /*the palette must have room for up to 256 colors with 4 bytes each.*/ + if(!info->palette) info->palette = (unsigned char*)lodepng_malloc(1024); + if(!info->palette) return; /*alloc fail*/ + for(i = 0; i != 256; ++i) { + /*Initialize all unused colors with black, the value used for invalid palette indices. + This is an error according to the PNG spec, but common PNG decoders make it black instead. + That makes color conversion slightly faster due to no error handling needed.*/ + info->palette[i * 4 + 0] = 0; + info->palette[i * 4 + 1] = 0; + info->palette[i * 4 + 2] = 0; + info->palette[i * 4 + 3] = 255; + } +} + +void lodepng_color_mode_cleanup(LodePNGColorMode* info) { + lodepng_palette_clear(info); +} + +unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source) { + lodepng_color_mode_cleanup(dest); + lodepng_memcpy(dest, source, sizeof(LodePNGColorMode)); + if(source->palette) { + dest->palette = (unsigned char*)lodepng_malloc(1024); + if(!dest->palette && source->palettesize) return 83; /*alloc fail*/ + lodepng_memcpy(dest->palette, source->palette, source->palettesize * 4); + } + return 0; +} + +LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth) { + LodePNGColorMode result; + lodepng_color_mode_init(&result); + result.colortype = colortype; + result.bitdepth = bitdepth; + return result; +} + +static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b) { + size_t i; + if(a->colortype != b->colortype) return 0; + if(a->bitdepth != b->bitdepth) return 0; + if(a->key_defined != b->key_defined) return 0; + if(a->key_defined) { + if(a->key_r != b->key_r) return 0; + if(a->key_g != b->key_g) return 0; + if(a->key_b != b->key_b) return 0; + } + if(a->palettesize != b->palettesize) return 0; + for(i = 0; i != a->palettesize * 4; ++i) { + if(a->palette[i] != b->palette[i]) return 0; + } + return 1; +} + +void lodepng_palette_clear(LodePNGColorMode* info) { + if(info->palette) lodepng_free(info->palette); + info->palette = 0; + info->palettesize = 0; +} + +unsigned lodepng_palette_add(LodePNGColorMode* info, + unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + if(!info->palette) /*allocate palette if empty*/ { + lodepng_color_mode_alloc_palette(info); + if(!info->palette) return 83; /*alloc fail*/ + } + if(info->palettesize >= 256) { + return 108; /*too many palette values*/ + } + info->palette[4 * info->palettesize + 0] = r; + info->palette[4 * info->palettesize + 1] = g; + info->palette[4 * info->palettesize + 2] = b; + info->palette[4 * info->palettesize + 3] = a; + ++info->palettesize; + return 0; +} + +/*calculate bits per pixel out of colortype and bitdepth*/ +unsigned lodepng_get_bpp(const LodePNGColorMode* info) { + return lodepng_get_bpp_lct(info->colortype, info->bitdepth); +} + +unsigned lodepng_get_channels(const LodePNGColorMode* info) { + return getNumColorChannels(info->colortype); +} + +unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info) { + return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA; +} + +unsigned lodepng_is_alpha_type(const LodePNGColorMode* info) { + return (info->colortype & 4) != 0; /*4 or 6*/ +} + +unsigned lodepng_is_palette_type(const LodePNGColorMode* info) { + return info->colortype == LCT_PALETTE; +} + +unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info) { + size_t i; + for(i = 0; i != info->palettesize; ++i) { + if(info->palette[i * 4 + 3] < 255) return 1; + } + return 0; +} + +unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) { + return info->key_defined + || lodepng_is_alpha_type(info) + || lodepng_has_palette_alpha(info); +} + +static size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) { + size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); + size_t n = (size_t)w * (size_t)h; + return ((n / 8u) * bpp) + ((n & 7u) * bpp + 7u) / 8u; +} + +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) { + return lodepng_get_raw_size_lct(w, h, color->colortype, color->bitdepth); +} + + +#ifdef LODEPNG_COMPILE_PNG + +/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer, +and in addition has one extra byte per line: the filter byte. So this gives a larger +result than lodepng_get_raw_size. Set h to 1 to get the size of 1 row including filter byte. */ +static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, unsigned bpp) { + /* + 1 for the filter byte, and possibly plus padding bits per line. */ + /* Ignoring casts, the expression is equal to (w * bpp + 7) / 8 + 1, but avoids overflow of w * bpp */ + size_t line = ((size_t)(w / 8u) * bpp) + 1u + ((w & 7u) * bpp + 7u) / 8u; + return (size_t)h * line; +} + +#ifdef LODEPNG_COMPILE_DECODER +/*Safely checks whether size_t overflow can be caused due to amount of pixels. +This check is overcautious rather than precise. If this check indicates no overflow, +you can safely compute in a size_t (but not an unsigned): +-(size_t)w * (size_t)h * 8 +-amount of bytes in IDAT (including filter, padding and Adam7 bytes) +-amount of bytes in raw color model +Returns 1 if overflow possible, 0 if not. +*/ +static int lodepng_pixel_overflow(unsigned w, unsigned h, + const LodePNGColorMode* pngcolor, const LodePNGColorMode* rawcolor) { + size_t bpp = LODEPNG_MAX(lodepng_get_bpp(pngcolor), lodepng_get_bpp(rawcolor)); + size_t numpixels, total; + size_t line; /* bytes per line in worst case */ + + if(lodepng_mulofl((size_t)w, (size_t)h, &numpixels)) return 1; + if(lodepng_mulofl(numpixels, 8, &total)) return 1; /* bit pointer with 8-bit color, or 8 bytes per channel color */ + + /* Bytes per scanline with the expression "(w / 8u) * bpp) + ((w & 7u) * bpp + 7u) / 8u" */ + if(lodepng_mulofl((size_t)(w / 8u), bpp, &line)) return 1; + if(lodepng_addofl(line, ((w & 7u) * bpp + 7u) / 8u, &line)) return 1; + + if(lodepng_addofl(line, 5, &line)) return 1; /* 5 bytes overhead per line: 1 filterbyte, 4 for Adam7 worst case */ + if(lodepng_mulofl(line, h, &total)) return 1; /* Total bytes in worst case */ + + return 0; /* no overflow */ +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +static void LodePNGUnknownChunks_init(LodePNGInfo* info) { + unsigned i; + for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0; + for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0; +} + +static void LodePNGUnknownChunks_cleanup(LodePNGInfo* info) { + unsigned i; + for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]); +} + +static unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src) { + unsigned i; + + LodePNGUnknownChunks_cleanup(dest); + + for(i = 0; i != 3; ++i) { + size_t j; + dest->unknown_chunks_size[i] = src->unknown_chunks_size[i]; + dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]); + if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/ + for(j = 0; j < src->unknown_chunks_size[i]; ++j) { + dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j]; + } + } + + return 0; +} + +/******************************************************************************/ + +static void LodePNGText_init(LodePNGInfo* info) { + info->text_num = 0; + info->text_keys = NULL; + info->text_strings = NULL; +} + +static void LodePNGText_cleanup(LodePNGInfo* info) { + size_t i; + for(i = 0; i != info->text_num; ++i) { + string_cleanup(&info->text_keys[i]); + string_cleanup(&info->text_strings[i]); + } + lodepng_free(info->text_keys); + lodepng_free(info->text_strings); +} + +static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) { + size_t i = 0; + dest->text_keys = NULL; + dest->text_strings = NULL; + dest->text_num = 0; + for(i = 0; i != source->text_num; ++i) { + CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i])); + } + return 0; +} + +static unsigned lodepng_add_text_sized(LodePNGInfo* info, const char* key, const char* str, size_t size) { + char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1))); + char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1))); + + if(new_keys) info->text_keys = new_keys; + if(new_strings) info->text_strings = new_strings; + + if(!new_keys || !new_strings) return 83; /*alloc fail*/ + + ++info->text_num; + info->text_keys[info->text_num - 1] = alloc_string(key); + info->text_strings[info->text_num - 1] = alloc_string_sized(str, size); + if(!info->text_keys[info->text_num - 1] || !info->text_strings[info->text_num - 1]) return 83; /*alloc fail*/ + + return 0; +} + +unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str) { + return lodepng_add_text_sized(info, key, str, lodepng_strlen(str)); +} + +void lodepng_clear_text(LodePNGInfo* info) { + LodePNGText_cleanup(info); +} + +/******************************************************************************/ + +static void LodePNGIText_init(LodePNGInfo* info) { + info->itext_num = 0; + info->itext_keys = NULL; + info->itext_langtags = NULL; + info->itext_transkeys = NULL; + info->itext_strings = NULL; +} + +static void LodePNGIText_cleanup(LodePNGInfo* info) { + size_t i; + for(i = 0; i != info->itext_num; ++i) { + string_cleanup(&info->itext_keys[i]); + string_cleanup(&info->itext_langtags[i]); + string_cleanup(&info->itext_transkeys[i]); + string_cleanup(&info->itext_strings[i]); + } + lodepng_free(info->itext_keys); + lodepng_free(info->itext_langtags); + lodepng_free(info->itext_transkeys); + lodepng_free(info->itext_strings); +} + +static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) { + size_t i = 0; + dest->itext_keys = NULL; + dest->itext_langtags = NULL; + dest->itext_transkeys = NULL; + dest->itext_strings = NULL; + dest->itext_num = 0; + for(i = 0; i != source->itext_num; ++i) { + CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i], + source->itext_transkeys[i], source->itext_strings[i])); + } + return 0; +} + +void lodepng_clear_itext(LodePNGInfo* info) { + LodePNGIText_cleanup(info); +} + +static unsigned lodepng_add_itext_sized(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str, size_t size) { + char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1))); + char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1))); + char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1))); + char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1))); + + if(new_keys) info->itext_keys = new_keys; + if(new_langtags) info->itext_langtags = new_langtags; + if(new_transkeys) info->itext_transkeys = new_transkeys; + if(new_strings) info->itext_strings = new_strings; + + if(!new_keys || !new_langtags || !new_transkeys || !new_strings) return 83; /*alloc fail*/ + + ++info->itext_num; + + info->itext_keys[info->itext_num - 1] = alloc_string(key); + info->itext_langtags[info->itext_num - 1] = alloc_string(langtag); + info->itext_transkeys[info->itext_num - 1] = alloc_string(transkey); + info->itext_strings[info->itext_num - 1] = alloc_string_sized(str, size); + + return 0; +} + +unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str) { + return lodepng_add_itext_sized(info, key, langtag, transkey, str, lodepng_strlen(str)); +} + +/* same as set but does not delete */ +static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) { + if(profile_size == 0) return 100; /*invalid ICC profile size*/ + + info->iccp_name = alloc_string(name); + info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size); + + if(!info->iccp_name || !info->iccp_profile) return 83; /*alloc fail*/ + + lodepng_memcpy(info->iccp_profile, profile, profile_size); + info->iccp_profile_size = profile_size; + + return 0; /*ok*/ +} + +unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) { + if(info->iccp_name) lodepng_clear_icc(info); + info->iccp_defined = 1; + + return lodepng_assign_icc(info, name, profile, profile_size); +} + +void lodepng_clear_icc(LodePNGInfo* info) { + string_cleanup(&info->iccp_name); + lodepng_free(info->iccp_profile); + info->iccp_profile = NULL; + info->iccp_profile_size = 0; + info->iccp_defined = 0; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +void lodepng_info_init(LodePNGInfo* info) { + lodepng_color_mode_init(&info->color); + info->interlace_method = 0; + info->compression_method = 0; + info->filter_method = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + info->background_defined = 0; + info->background_r = info->background_g = info->background_b = 0; + + LodePNGText_init(info); + LodePNGIText_init(info); + + info->time_defined = 0; + info->phys_defined = 0; + + info->gama_defined = 0; + info->chrm_defined = 0; + info->srgb_defined = 0; + info->iccp_defined = 0; + info->iccp_name = NULL; + info->iccp_profile = NULL; + + info->sbit_defined = 0; + info->sbit_r = info->sbit_g = info->sbit_b = info->sbit_a = 0; + + LodePNGUnknownChunks_init(info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +void lodepng_info_cleanup(LodePNGInfo* info) { + lodepng_color_mode_cleanup(&info->color); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + LodePNGText_cleanup(info); + LodePNGIText_cleanup(info); + + lodepng_clear_icc(info); + + LodePNGUnknownChunks_cleanup(info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) { + lodepng_info_cleanup(dest); + lodepng_memcpy(dest, source, sizeof(LodePNGInfo)); + lodepng_color_mode_init(&dest->color); + CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color)); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + CERROR_TRY_RETURN(LodePNGText_copy(dest, source)); + CERROR_TRY_RETURN(LodePNGIText_copy(dest, source)); + if(source->iccp_defined) { + CERROR_TRY_RETURN(lodepng_assign_icc(dest, source->iccp_name, source->iccp_profile, source->iccp_profile_size)); + } + + LodePNGUnknownChunks_init(dest); + CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source)); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + return 0; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/ +static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) { + unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/ + /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/ + unsigned p = index & m; + in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/ + in = in << (bits * (m - p)); + if(p == 0) out[index * bits / 8u] = in; + else out[index * bits / 8u] |= in; +} + +typedef struct ColorTree ColorTree; + +/* +One node of a color tree +This is the data structure used to count the number of unique colors and to get a palette +index for a color. It's like an octree, but because the alpha channel is used too, each +node has 16 instead of 8 children. +*/ +struct ColorTree { + ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/ + int index; /*the payload. Only has a meaningful value if this is in the last level*/ +}; + +static void color_tree_init(ColorTree* tree) { + lodepng_memset(tree->children, 0, 16 * sizeof(*tree->children)); + tree->index = -1; +} + +static void color_tree_cleanup(ColorTree* tree) { + int i; + for(i = 0; i != 16; ++i) { + if(tree->children[i]) { + color_tree_cleanup(tree->children[i]); + lodepng_free(tree->children[i]); + } + } +} + +/*returns -1 if color not present, its index otherwise*/ +static int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + int bit = 0; + for(bit = 0; bit < 8; ++bit) { + int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); + if(!tree->children[i]) return -1; + else tree = tree->children[i]; + } + return tree ? tree->index : -1; +} + +#ifdef LODEPNG_COMPILE_ENCODER +static int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + return color_tree_get(tree, r, g, b, a) >= 0; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/*color is not allowed to already exist. +Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist") +Returns error code, or 0 if ok*/ +static unsigned color_tree_add(ColorTree* tree, + unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) { + int bit; + for(bit = 0; bit < 8; ++bit) { + int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); + if(!tree->children[i]) { + tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree)); + if(!tree->children[i]) return 83; /*alloc fail*/ + color_tree_init(tree->children[i]); + } + tree = tree->children[i]; + } + tree->index = (int)index; + return 0; +} + +/*put a pixel, given its RGBA color, into image of any color type*/ +static unsigned rgba8ToPixel(unsigned char* out, size_t i, + const LodePNGColorMode* mode, ColorTree* tree /*for palette*/, + unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + if(mode->colortype == LCT_GREY) { + unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ + if(mode->bitdepth == 8) out[i] = gray; + else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = gray; + else { + /*take the most significant bits of gray*/ + gray = ((unsigned)gray >> (8u - mode->bitdepth)) & ((1u << mode->bitdepth) - 1u); + addColorBits(out, i, mode->bitdepth, gray); + } + } else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + out[i * 3 + 0] = r; + out[i * 3 + 1] = g; + out[i * 3 + 2] = b; + } else { + out[i * 6 + 0] = out[i * 6 + 1] = r; + out[i * 6 + 2] = out[i * 6 + 3] = g; + out[i * 6 + 4] = out[i * 6 + 5] = b; + } + } else if(mode->colortype == LCT_PALETTE) { + int index = color_tree_get(tree, r, g, b, a); + if(index < 0) return 82; /*color not in palette*/ + if(mode->bitdepth == 8) out[i] = index; + else addColorBits(out, i, mode->bitdepth, (unsigned)index); + } else if(mode->colortype == LCT_GREY_ALPHA) { + unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ + if(mode->bitdepth == 8) { + out[i * 2 + 0] = gray; + out[i * 2 + 1] = a; + } else if(mode->bitdepth == 16) { + out[i * 4 + 0] = out[i * 4 + 1] = gray; + out[i * 4 + 2] = out[i * 4 + 3] = a; + } + } else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + out[i * 4 + 0] = r; + out[i * 4 + 1] = g; + out[i * 4 + 2] = b; + out[i * 4 + 3] = a; + } else { + out[i * 8 + 0] = out[i * 8 + 1] = r; + out[i * 8 + 2] = out[i * 8 + 3] = g; + out[i * 8 + 4] = out[i * 8 + 5] = b; + out[i * 8 + 6] = out[i * 8 + 7] = a; + } + } + + return 0; /*no error*/ +} + +/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/ +static void rgba16ToPixel(unsigned char* out, size_t i, + const LodePNGColorMode* mode, + unsigned short r, unsigned short g, unsigned short b, unsigned short a) { + if(mode->colortype == LCT_GREY) { + unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/ + out[i * 2 + 0] = (gray >> 8) & 255; + out[i * 2 + 1] = gray & 255; + } else if(mode->colortype == LCT_RGB) { + out[i * 6 + 0] = (r >> 8) & 255; + out[i * 6 + 1] = r & 255; + out[i * 6 + 2] = (g >> 8) & 255; + out[i * 6 + 3] = g & 255; + out[i * 6 + 4] = (b >> 8) & 255; + out[i * 6 + 5] = b & 255; + } else if(mode->colortype == LCT_GREY_ALPHA) { + unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/ + out[i * 4 + 0] = (gray >> 8) & 255; + out[i * 4 + 1] = gray & 255; + out[i * 4 + 2] = (a >> 8) & 255; + out[i * 4 + 3] = a & 255; + } else if(mode->colortype == LCT_RGBA) { + out[i * 8 + 0] = (r >> 8) & 255; + out[i * 8 + 1] = r & 255; + out[i * 8 + 2] = (g >> 8) & 255; + out[i * 8 + 3] = g & 255; + out[i * 8 + 4] = (b >> 8) & 255; + out[i * 8 + 5] = b & 255; + out[i * 8 + 6] = (a >> 8) & 255; + out[i * 8 + 7] = a & 255; + } +} + +/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/ +static void getPixelColorRGBA8(unsigned char* r, unsigned char* g, + unsigned char* b, unsigned char* a, + const unsigned char* in, size_t i, + const LodePNGColorMode* mode) { + if(mode->colortype == LCT_GREY) { + if(mode->bitdepth == 8) { + *r = *g = *b = in[i]; + if(mode->key_defined && *r == mode->key_r) *a = 0; + else *a = 255; + } else if(mode->bitdepth == 16) { + *r = *g = *b = in[i * 2 + 0]; + if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; + else *a = 255; + } else { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = i * mode->bitdepth; + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + *r = *g = *b = (value * 255) / highest; + if(mode->key_defined && value == mode->key_r) *a = 0; + else *a = 255; + } + } else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2]; + if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0; + else *a = 255; + } else { + *r = in[i * 6 + 0]; + *g = in[i * 6 + 2]; + *b = in[i * 6 + 4]; + if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + else *a = 255; + } + } else if(mode->colortype == LCT_PALETTE) { + unsigned index; + if(mode->bitdepth == 8) index = in[i]; + else { + size_t j = i * mode->bitdepth; + index = readBitsFromReversedStream(&j, in, mode->bitdepth); + } + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + *r = mode->palette[index * 4 + 0]; + *g = mode->palette[index * 4 + 1]; + *b = mode->palette[index * 4 + 2]; + *a = mode->palette[index * 4 + 3]; + } else if(mode->colortype == LCT_GREY_ALPHA) { + if(mode->bitdepth == 8) { + *r = *g = *b = in[i * 2 + 0]; + *a = in[i * 2 + 1]; + } else { + *r = *g = *b = in[i * 4 + 0]; + *a = in[i * 4 + 2]; + } + } else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + *r = in[i * 4 + 0]; + *g = in[i * 4 + 1]; + *b = in[i * 4 + 2]; + *a = in[i * 4 + 3]; + } else { + *r = in[i * 8 + 0]; + *g = in[i * 8 + 2]; + *b = in[i * 8 + 4]; + *a = in[i * 8 + 6]; + } + } +} + +/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color +mode test cases, optimized to convert the colors much faster, when converting +to the common case of RGBA with 8 bit per channel. buffer must be RGBA with +enough memory.*/ +static void getPixelColorsRGBA8(unsigned char* LODEPNG_RESTRICT buffer, size_t numpixels, + const unsigned char* LODEPNG_RESTRICT in, + const LodePNGColorMode* mode) { + unsigned num_channels = 4; + size_t i; + if(mode->colortype == LCT_GREY) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i]; + buffer[3] = 255; + } + if(mode->key_defined) { + buffer -= numpixels * num_channels; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + if(buffer[0] == mode->key_r) buffer[3] = 0; + } + } + } else if(mode->bitdepth == 16) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2]; + buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255; + } + } else { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; + buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255; + } + } + } else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + lodepng_memcpy(buffer, &in[i * 3], 3); + buffer[3] = 255; + } + if(mode->key_defined) { + buffer -= numpixels * num_channels; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + if(buffer[0] == mode->key_r && buffer[1]== mode->key_g && buffer[2] == mode->key_b) buffer[3] = 0; + } + } + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 6 + 0]; + buffer[1] = in[i * 6 + 2]; + buffer[2] = in[i * 6 + 4]; + buffer[3] = mode->key_defined + && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255; + } + } + } else if(mode->colortype == LCT_PALETTE) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = in[i]; + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 4); + } + } else { + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth); + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 4); + } + } + } else if(mode->colortype == LCT_GREY_ALPHA) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; + buffer[3] = in[i * 2 + 1]; + } + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; + buffer[3] = in[i * 4 + 2]; + } + } + } else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + lodepng_memcpy(buffer, in, numpixels * 4); + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 8 + 0]; + buffer[1] = in[i * 8 + 2]; + buffer[2] = in[i * 8 + 4]; + buffer[3] = in[i * 8 + 6]; + } + } + } +} + +/*Similar to getPixelColorsRGBA8, but with 3-channel RGB output.*/ +static void getPixelColorsRGB8(unsigned char* LODEPNG_RESTRICT buffer, size_t numpixels, + const unsigned char* LODEPNG_RESTRICT in, + const LodePNGColorMode* mode) { + const unsigned num_channels = 3; + size_t i; + if(mode->colortype == LCT_GREY) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i]; + } + } else if(mode->bitdepth == 16) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2]; + } + } else { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; + } + } + } else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + lodepng_memcpy(buffer, in, numpixels * 3); + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 6 + 0]; + buffer[1] = in[i * 6 + 2]; + buffer[2] = in[i * 6 + 4]; + } + } + } else if(mode->colortype == LCT_PALETTE) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = in[i]; + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 3); + } + } else { + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth); + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 3); + } + } + } else if(mode->colortype == LCT_GREY_ALPHA) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; + } + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; + } + } + } else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + lodepng_memcpy(buffer, &in[i * 4], 3); + } + } else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 8 + 0]; + buffer[1] = in[i * 8 + 2]; + buffer[2] = in[i * 8 + 4]; + } + } + } +} + +/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with +given color type, but the given color type must be 16-bit itself.*/ +static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a, + const unsigned char* in, size_t i, const LodePNGColorMode* mode) { + if(mode->colortype == LCT_GREY) { + *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1]; + if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; + else *a = 65535; + } else if(mode->colortype == LCT_RGB) { + *r = 256u * in[i * 6 + 0] + in[i * 6 + 1]; + *g = 256u * in[i * 6 + 2] + in[i * 6 + 3]; + *b = 256u * in[i * 6 + 4] + in[i * 6 + 5]; + if(mode->key_defined + && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + else *a = 65535; + } else if(mode->colortype == LCT_GREY_ALPHA) { + *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1]; + *a = 256u * in[i * 4 + 2] + in[i * 4 + 3]; + } else if(mode->colortype == LCT_RGBA) { + *r = 256u * in[i * 8 + 0] + in[i * 8 + 1]; + *g = 256u * in[i * 8 + 2] + in[i * 8 + 3]; + *b = 256u * in[i * 8 + 4] + in[i * 8 + 5]; + *a = 256u * in[i * 8 + 6] + in[i * 8 + 7]; + } +} + +unsigned lodepng_convert(unsigned char* out, const unsigned char* in, + const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, + unsigned w, unsigned h) { + size_t i; + ColorTree tree; + size_t numpixels = (size_t)w * (size_t)h; + unsigned error = 0; + + if(mode_in->colortype == LCT_PALETTE && !mode_in->palette) { + return 107; /* error: must provide palette if input mode is palette */ + } + + if(lodepng_color_mode_equal(mode_out, mode_in)) { + size_t numbytes = lodepng_get_raw_size(w, h, mode_in); + lodepng_memcpy(out, in, numbytes); + return 0; + } + + if(mode_out->colortype == LCT_PALETTE) { + size_t palettesize = mode_out->palettesize; + const unsigned char* palette = mode_out->palette; + size_t palsize = (size_t)1u << mode_out->bitdepth; + /*if the user specified output palette but did not give the values, assume + they want the values of the input color type (assuming that one is palette). + Note that we never create a new palette ourselves.*/ + if(palettesize == 0) { + palettesize = mode_in->palettesize; + palette = mode_in->palette; + /*if the input was also palette with same bitdepth, then the color types are also + equal, so copy literally. This to preserve the exact indices that were in the PNG + even in case there are duplicate colors in the palette.*/ + if(mode_in->colortype == LCT_PALETTE && mode_in->bitdepth == mode_out->bitdepth) { + size_t numbytes = lodepng_get_raw_size(w, h, mode_in); + lodepng_memcpy(out, in, numbytes); + return 0; + } + } + if(palettesize < palsize) palsize = palettesize; + color_tree_init(&tree); + for(i = 0; i != palsize; ++i) { + const unsigned char* p = &palette[i * 4]; + error = color_tree_add(&tree, p[0], p[1], p[2], p[3], (unsigned)i); + if(error) break; + } + } + + if(!error) { + if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16) { + for(i = 0; i != numpixels; ++i) { + unsigned short r = 0, g = 0, b = 0, a = 0; + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + rgba16ToPixel(out, i, mode_out, r, g, b, a); + } + } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) { + getPixelColorsRGBA8(out, numpixels, in, mode_in); + } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) { + getPixelColorsRGB8(out, numpixels, in, mode_in); + } else { + unsigned char r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a); + if(error) break; + } + } + } + + if(mode_out->colortype == LCT_PALETTE) { + color_tree_cleanup(&tree); + } + + return error; +} + + +/* Converts a single rgb color without alpha from one type to another, color bits truncated to +their bitdepth. In case of single channel (gray or palette), only the r channel is used. Slow +function, do not use to process all pixels of an image. Alpha channel not supported on purpose: +this is for bKGD, supporting alpha may prevent it from finding a color in the palette, from the +specification it looks like bKGD should ignore the alpha values of the palette since it can use +any palette index but doesn't have an alpha channel. Idem with ignoring color key. */ +unsigned lodepng_convert_rgb( + unsigned* r_out, unsigned* g_out, unsigned* b_out, + unsigned r_in, unsigned g_in, unsigned b_in, + const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in) { + unsigned r = 0, g = 0, b = 0; + unsigned mul = 65535 / ((1u << mode_in->bitdepth) - 1u); /*65535, 21845, 4369, 257, 1*/ + unsigned shift = 16 - mode_out->bitdepth; + + if(mode_in->colortype == LCT_GREY || mode_in->colortype == LCT_GREY_ALPHA) { + r = g = b = r_in * mul; + } else if(mode_in->colortype == LCT_RGB || mode_in->colortype == LCT_RGBA) { + r = r_in * mul; + g = g_in * mul; + b = b_in * mul; + } else if(mode_in->colortype == LCT_PALETTE) { + if(r_in >= mode_in->palettesize) return 82; + r = mode_in->palette[r_in * 4 + 0] * 257u; + g = mode_in->palette[r_in * 4 + 1] * 257u; + b = mode_in->palette[r_in * 4 + 2] * 257u; + } else { + return 31; + } + + /* now convert to output format */ + if(mode_out->colortype == LCT_GREY || mode_out->colortype == LCT_GREY_ALPHA) { + *r_out = r >> shift ; + } else if(mode_out->colortype == LCT_RGB || mode_out->colortype == LCT_RGBA) { + *r_out = r >> shift ; + *g_out = g >> shift ; + *b_out = b >> shift ; + } else if(mode_out->colortype == LCT_PALETTE) { + unsigned i; + /* a 16-bit color cannot be in the palette */ + if((r >> 8) != (r & 255) || (g >> 8) != (g & 255) || (b >> 8) != (b & 255)) return 82; + for(i = 0; i < mode_out->palettesize; i++) { + unsigned j = i * 4; + if((r >> 8) == mode_out->palette[j + 0] && (g >> 8) == mode_out->palette[j + 1] && + (b >> 8) == mode_out->palette[j + 2]) { + *r_out = i; + return 0; + } + } + return 82; + } else { + return 31; + } + + return 0; +} + +#ifdef LODEPNG_COMPILE_ENCODER + +void lodepng_color_stats_init(LodePNGColorStats* stats) { + /*stats*/ + stats->colored = 0; + stats->key = 0; + stats->key_r = stats->key_g = stats->key_b = 0; + stats->alpha = 0; + stats->numcolors = 0; + stats->bits = 1; + stats->numpixels = 0; + /*settings*/ + stats->allow_palette = 1; + stats->allow_greyscale = 1; +} + +/*function used for debug purposes with C++*/ +/*void printColorStats(LodePNGColorStats* p) { + std::cout << "colored: " << (int)p->colored << ", "; + std::cout << "key: " << (int)p->key << ", "; + std::cout << "key_r: " << (int)p->key_r << ", "; + std::cout << "key_g: " << (int)p->key_g << ", "; + std::cout << "key_b: " << (int)p->key_b << ", "; + std::cout << "alpha: " << (int)p->alpha << ", "; + std::cout << "numcolors: " << (int)p->numcolors << ", "; + std::cout << "bits: " << (int)p->bits << std::endl; +}*/ + +/*Returns how many bits needed to represent given value (max 8 bit)*/ +static unsigned getValueRequiredBits(unsigned char value) { + if(value == 0 || value == 255) return 1; + /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/ + if(value % 17 == 0) return value % 85 == 0 ? 2 : 4; + return 8; +} + +/*stats must already have been inited. */ +unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, + const unsigned char* in, unsigned w, unsigned h, + const LodePNGColorMode* mode_in) { + size_t i; + ColorTree tree; + size_t numpixels = (size_t)w * (size_t)h; + unsigned error = 0; + + /* mark things as done already if it would be impossible to have a more expensive case */ + unsigned colored_done = lodepng_is_greyscale_type(mode_in) ? 1 : 0; + unsigned alpha_done = lodepng_can_have_alpha(mode_in) ? 0 : 1; + unsigned numcolors_done = 0; + unsigned bpp = lodepng_get_bpp(mode_in); + unsigned bits_done = (stats->bits == 1 && bpp == 1) ? 1 : 0; + unsigned sixteen = 0; /* whether the input image is 16 bit */ + unsigned maxnumcolors = 257; + if(bpp <= 8) maxnumcolors = LODEPNG_MIN(257, stats->numcolors + (1u << bpp)); + + stats->numpixels += numpixels; + + /*if palette not allowed, no need to compute numcolors*/ + if(!stats->allow_palette) numcolors_done = 1; + + color_tree_init(&tree); + + /*If the stats was already filled in from previous data, fill its palette in tree + and mark things as done already if we know they are the most expensive case already*/ + if(stats->alpha) alpha_done = 1; + if(stats->colored) colored_done = 1; + if(stats->bits == 16) numcolors_done = 1; + if(stats->bits >= bpp) bits_done = 1; + if(stats->numcolors >= maxnumcolors) numcolors_done = 1; + + if(!numcolors_done) { + for(i = 0; i < stats->numcolors; i++) { + const unsigned char* color = &stats->palette[i * 4]; + error = color_tree_add(&tree, color[0], color[1], color[2], color[3], i); + if(error) goto cleanup; + } + } + + /*Check if the 16-bit input is truly 16-bit*/ + if(mode_in->bitdepth == 16 && !sixteen) { + unsigned short r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) || + (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/ { + stats->bits = 16; + sixteen = 1; + bits_done = 1; + numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/ + break; + } + } + } + + if(sixteen) { + unsigned short r = 0, g = 0, b = 0, a = 0; + + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + + if(!colored_done && (r != g || r != b)) { + stats->colored = 1; + colored_done = 1; + } + + if(!alpha_done) { + unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b); + if(a != 65535 && (a != 0 || (stats->key && !matchkey))) { + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + } else if(a == 0 && !stats->alpha && !stats->key) { + stats->key = 1; + stats->key_r = r; + stats->key_g = g; + stats->key_b = b; + } else if(a == 65535 && stats->key && matchkey) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + } + } + if(alpha_done && numcolors_done && colored_done && bits_done) break; + } + + if(stats->key && !stats->alpha) { + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + } + } + } + } else /* < 16-bit */ { + unsigned char r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + + if(!bits_done && stats->bits < 8) { + /*only r is checked, < 8 bits is only relevant for grayscale*/ + unsigned bits = getValueRequiredBits(r); + if(bits > stats->bits) stats->bits = bits; + } + bits_done = (stats->bits >= bpp); + + if(!colored_done && (r != g || r != b)) { + stats->colored = 1; + colored_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/ + } + + if(!alpha_done) { + unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b); + if(a != 255 && (a != 0 || (stats->key && !matchkey))) { + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } else if(a == 0 && !stats->alpha && !stats->key) { + stats->key = 1; + stats->key_r = r; + stats->key_g = g; + stats->key_b = b; + } else if(a == 255 && stats->key && matchkey) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + } + + if(!numcolors_done) { + if(!color_tree_has(&tree, r, g, b, a)) { + error = color_tree_add(&tree, r, g, b, a, stats->numcolors); + if(error) goto cleanup; + if(stats->numcolors < 256) { + unsigned char* p = stats->palette; + unsigned n = stats->numcolors; + p[n * 4 + 0] = r; + p[n * 4 + 1] = g; + p[n * 4 + 2] = b; + p[n * 4 + 3] = a; + } + ++stats->numcolors; + numcolors_done = stats->numcolors >= maxnumcolors; + } + } + + if(alpha_done && numcolors_done && colored_done && bits_done) break; + } + + if(stats->key && !stats->alpha) { + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + } + } + + /*make the stats's key always 16-bit for consistency - repeat each byte twice*/ + stats->key_r += (stats->key_r << 8); + stats->key_g += (stats->key_g << 8); + stats->key_b += (stats->key_b << 8); + } + +cleanup: + color_tree_cleanup(&tree); + return error; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*Adds a single color to the color stats. The stats must already have been inited. The color must be given as 16-bit +(with 2 bytes repeating for 8-bit and 65535 for opaque alpha channel). This function is expensive, do not call it for +all pixels of an image but only for a few additional values. */ +static unsigned lodepng_color_stats_add(LodePNGColorStats* stats, + unsigned r, unsigned g, unsigned b, unsigned a) { + unsigned error = 0; + unsigned char image[8]; + LodePNGColorMode mode; + lodepng_color_mode_init(&mode); + image[0] = r >> 8; image[1] = r; image[2] = g >> 8; image[3] = g; + image[4] = b >> 8; image[5] = b; image[6] = a >> 8; image[7] = a; + mode.bitdepth = 16; + mode.colortype = LCT_RGBA; + error = lodepng_compute_color_stats(stats, image, 1, 1, &mode); + lodepng_color_mode_cleanup(&mode); + return error; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/*Computes a minimal PNG color model that can contain all colors as indicated by the stats. +The stats should be computed with lodepng_compute_color_stats. +mode_in is raw color profile of the image the stats were computed on, to copy palette order from when relevant. +Minimal PNG color model means the color type and bit depth that gives smallest amount of bits in the output image, +e.g. gray if only grayscale pixels, palette if less than 256 colors, color key if only single transparent color, ... +This is used if auto_convert is enabled (it is by default). +*/ +static unsigned auto_choose_color(LodePNGColorMode* mode_out, + const LodePNGColorMode* mode_in, + const LodePNGColorStats* stats) { + unsigned error = 0; + unsigned palettebits; + size_t i, n; + size_t numpixels = stats->numpixels; + unsigned palette_ok, gray_ok; + + unsigned alpha = stats->alpha; + unsigned key = stats->key; + unsigned bits = stats->bits; + + mode_out->key_defined = 0; + + if(key && numpixels <= 16) { + alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ + key = 0; + if(bits < 8) bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + + gray_ok = !stats->colored; + if(!stats->allow_greyscale) gray_ok = 0; + if(!gray_ok && bits < 8) bits = 8; + + n = stats->numcolors; + palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); + palette_ok = n <= 256 && bits <= 8 && n != 0; /*n==0 means likely numcolors wasn't computed*/ + if(numpixels < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ + if(gray_ok && !alpha && bits <= palettebits) palette_ok = 0; /*gray is less overhead*/ + if(!stats->allow_palette) palette_ok = 0; + + if(palette_ok) { + const unsigned char* p = stats->palette; + lodepng_palette_clear(mode_out); /*remove potential earlier palette*/ + for(i = 0; i != stats->numcolors; ++i) { + error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]); + if(error) break; + } + + mode_out->colortype = LCT_PALETTE; + mode_out->bitdepth = palettebits; + + if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize + && mode_in->bitdepth == mode_out->bitdepth) { + /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/ + lodepng_color_mode_cleanup(mode_out); /*clears palette, keeps the above set colortype and bitdepth fields as-is*/ + lodepng_color_mode_copy(mode_out, mode_in); + } + } else /*8-bit or 16-bit per channel*/ { + mode_out->bitdepth = bits; + mode_out->colortype = alpha ? (gray_ok ? LCT_GREY_ALPHA : LCT_RGBA) + : (gray_ok ? LCT_GREY : LCT_RGB); + if(key) { + unsigned mask = (1u << mode_out->bitdepth) - 1u; /*stats always uses 16-bit, mask converts it*/ + mode_out->key_r = stats->key_r & mask; + mode_out->key_g = stats->key_g & mask; + mode_out->key_b = stats->key_b & mask; + mode_out->key_defined = 1; + } + } + + return error; +} + +#endif /* #ifdef LODEPNG_COMPILE_ENCODER */ + +/*Paeth predictor, used by PNG filter type 4*/ +static unsigned char paethPredictor(unsigned char a, unsigned char b, unsigned char c) { + /* the subtractions of unsigned char cast it to a signed type. + With gcc, short is faster than int, with clang int is as fast (as of april 2023)*/ + short pa = (b - c) < 0 ? -(b - c) : (b - c); + short pb = (a - c) < 0 ? -(a - c) : (a - c); + /* writing it out like this compiles to something faster than introducing a temp variable*/ + short pc = (a + b - c - c) < 0 ? -(a + b - c - c) : (a + b - c - c); + /* return input value associated with smallest of pa, pb, pc (with certain priority if equal) */ + if(pb < pa) { a = b; pa = pb; } + return (pc < pa) ? c : a; +} + +/*shared values used by multiple Adam7 related functions*/ + +static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ +static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ +static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ +static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ + +/* +Outputs various dimensions and positions in the image related to the Adam7 reduced images. +passw: output containing the width of the 7 passes +passh: output containing the height of the 7 passes +filter_passstart: output containing the index of the start and end of each + reduced image with filter bytes +padded_passstart output containing the index of the start and end of each + reduced image when without filter bytes but with padded scanlines +passstart: output containing the index of the start and end of each reduced + image without padding between scanlines, but still padding between the images +w, h: width and height of non-interlaced image +bpp: bits per pixel +"padded" is only relevant if bpp is less than 8 and a scanline or image does not + end at a full byte +*/ +static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], + size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) { + /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/ + unsigned i; + + /*calculate width and height in pixels of each pass*/ + for(i = 0; i != 7; ++i) { + passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; + passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; + if(passw[i] == 0) passh[i] = 0; + if(passh[i] == 0) passw[i] = 0; + } + + filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; + for(i = 0; i != 7; ++i) { + /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ + filter_passstart[i + 1] = filter_passstart[i] + + ((passw[i] && passh[i]) ? passh[i] * (1u + (passw[i] * bpp + 7u) / 8u) : 0); + /*bits padded if needed to fill full byte at end of each scanline*/ + padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7u) / 8u); + /*only padded at end of reduced image*/ + passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7u) / 8u; + } +} + +#ifdef LODEPNG_COMPILE_DECODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG Decoder / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*read the information from the header and store it in the LodePNGInfo. return value is error*/ +unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state, + const unsigned char* in, size_t insize) { + unsigned width, height; + LodePNGInfo* info = &state->info_png; + if(insize == 0 || in == 0) { + CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/ + } + if(insize < 33) { + CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/ + } + + /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/ + /* TODO: remove this. One should use a new LodePNGState for new sessions */ + lodepng_info_cleanup(info); + lodepng_info_init(info); + + if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 + || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { + CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/ + } + if(lodepng_chunk_length(in + 8) != 13) { + CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/ + } + if(!lodepng_chunk_type_equals(in + 8, "IHDR")) { + CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/ + } + + /*read the values given in the header*/ + width = lodepng_read32bitInt(&in[16]); + height = lodepng_read32bitInt(&in[20]); + /*TODO: remove the undocumented feature that allows to give null pointers to width or height*/ + if(w) *w = width; + if(h) *h = height; + info->color.bitdepth = in[24]; + info->color.colortype = (LodePNGColorType)in[25]; + info->compression_method = in[26]; + info->filter_method = in[27]; + info->interlace_method = in[28]; + + /*errors returned only after the parsing so other values are still output*/ + + /*error: invalid image size*/ + if(width == 0 || height == 0) CERROR_RETURN_ERROR(state->error, 93); + /*error: invalid colortype or bitdepth combination*/ + state->error = checkColorValidity(info->color.colortype, info->color.bitdepth); + if(state->error) return state->error; + /*error: only compression method 0 is allowed in the specification*/ + if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32); + /*error: only filter method 0 is allowed in the specification*/ + if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33); + /*error: only interlace methods 0 and 1 exist in the specification*/ + if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34); + + if(!state->decoder.ignore_crc) { + unsigned CRC = lodepng_read32bitInt(&in[29]); + unsigned checksum = lodepng_crc32(&in[12], 17); + if(CRC != checksum) { + CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/ + } + } + + return state->error; +} + +static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, + size_t bytewidth, unsigned char filterType, size_t length) { + /* + For PNG filter method 0 + unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, + the filter works byte per byte (bytewidth = 1) + precon is the previous unfiltered scanline, recon the result, scanline the current one + the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead + recon and scanline MAY be the same memory address! precon must be disjoint. + */ + + size_t i; + switch(filterType) { + case 0: + for(i = 0; i != length; ++i) recon[i] = scanline[i]; + break; + case 1: { + size_t j = 0; + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; + for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + recon[j]; + break; + } + case 2: + if(precon) { + for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i]; + } else { + for(i = 0; i != length; ++i) recon[i] = scanline[i]; + } + break; + case 3: + if(precon) { + size_t j = 0; + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u); + /* Unroll independent paths of this predictor. A 6x and 8x version is also possible but that adds + too much code. Whether this speeds up anything depends on compiler and settings. */ + if(bytewidth >= 4) { + for(; i + 3 < length; i += 4, j += 4) { + unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3]; + unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3]; + unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3]; + recon[i + 0] = s0 + ((r0 + p0) >> 1u); + recon[i + 1] = s1 + ((r1 + p1) >> 1u); + recon[i + 2] = s2 + ((r2 + p2) >> 1u); + recon[i + 3] = s3 + ((r3 + p3) >> 1u); + } + } else if(bytewidth >= 3) { + for(; i + 2 < length; i += 3, j += 3) { + unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2]; + unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2]; + unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2]; + recon[i + 0] = s0 + ((r0 + p0) >> 1u); + recon[i + 1] = s1 + ((r1 + p1) >> 1u); + recon[i + 2] = s2 + ((r2 + p2) >> 1u); + } + } else if(bytewidth >= 2) { + for(; i + 1 < length; i += 2, j += 2) { + unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1]; + unsigned char r0 = recon[j + 0], r1 = recon[j + 1]; + unsigned char p0 = precon[i + 0], p1 = precon[i + 1]; + recon[i + 0] = s0 + ((r0 + p0) >> 1u); + recon[i + 1] = s1 + ((r1 + p1) >> 1u); + } + } + for(; i != length; ++i, ++j) recon[i] = scanline[i] + ((recon[j] + precon[i]) >> 1u); + } else { + size_t j = 0; + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; + for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + (recon[j] >> 1u); + } + break; + case 4: + if(precon) { + /* Unroll independent paths of this predictor. Whether this speeds up + anything depends on compiler and settings. */ + if(bytewidth == 8) { + unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0; + unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0; + unsigned char a4, b4 = 0, c4, d4 = 0, a5, b5 = 0, c5, d5 = 0; + unsigned char a6, b6 = 0, c6, d6 = 0, a7, b7 = 0, c7, d7 = 0; + for(i = 0; i + 7 < length; i += 8) { + c0 = b0; c1 = b1; c2 = b2; c3 = b3; + c4 = b4; c5 = b5; c6 = b6; c7 = b7; + b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; b3 = precon[i + 3]; + b4 = precon[i + 4]; b5 = precon[i + 5]; b6 = precon[i + 6]; b7 = precon[i + 7]; + a0 = d0; a1 = d1; a2 = d2; a3 = d3; + a4 = d4; a5 = d5; a6 = d6; a7 = d7; + d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); + d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); + d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); + d3 = scanline[i + 3] + paethPredictor(a3, b3, c3); + d4 = scanline[i + 4] + paethPredictor(a4, b4, c4); + d5 = scanline[i + 5] + paethPredictor(a5, b5, c5); + d6 = scanline[i + 6] + paethPredictor(a6, b6, c6); + d7 = scanline[i + 7] + paethPredictor(a7, b7, c7); + recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; recon[i + 3] = d3; + recon[i + 4] = d4; recon[i + 5] = d5; recon[i + 6] = d6; recon[i + 7] = d7; + } + } else if(bytewidth == 6) { + unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0; + unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0; + unsigned char a4, b4 = 0, c4, d4 = 0, a5, b5 = 0, c5, d5 = 0; + for(i = 0; i + 5 < length; i += 6) { + c0 = b0; c1 = b1; c2 = b2; + c3 = b3; c4 = b4; c5 = b5; + b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; + b3 = precon[i + 3]; b4 = precon[i + 4]; b5 = precon[i + 5]; + a0 = d0; a1 = d1; a2 = d2; + a3 = d3; a4 = d4; a5 = d5; + d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); + d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); + d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); + d3 = scanline[i + 3] + paethPredictor(a3, b3, c3); + d4 = scanline[i + 4] + paethPredictor(a4, b4, c4); + d5 = scanline[i + 5] + paethPredictor(a5, b5, c5); + recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; + recon[i + 3] = d3; recon[i + 4] = d4; recon[i + 5] = d5; + } + } else if(bytewidth == 4) { + unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0; + unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0; + for(i = 0; i + 3 < length; i += 4) { + c0 = b0; c1 = b1; c2 = b2; c3 = b3; + b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; b3 = precon[i + 3]; + a0 = d0; a1 = d1; a2 = d2; a3 = d3; + d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); + d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); + d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); + d3 = scanline[i + 3] + paethPredictor(a3, b3, c3); + recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; recon[i + 3] = d3; + } + } else if(bytewidth == 3) { + unsigned char a0, b0 = 0, c0, d0 = 0; + unsigned char a1, b1 = 0, c1, d1 = 0; + unsigned char a2, b2 = 0, c2, d2 = 0; + for(i = 0; i + 2 < length; i += 3) { + c0 = b0; c1 = b1; c2 = b2; + b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; + a0 = d0; a1 = d1; a2 = d2; + d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); + d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); + d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); + recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; + } + } else if(bytewidth == 2) { + unsigned char a0, b0 = 0, c0, d0 = 0; + unsigned char a1, b1 = 0, c1, d1 = 0; + for(i = 0; i + 1 < length; i += 2) { + c0 = b0; c1 = b1; + b0 = precon[i + 0]; + b1 = precon[i + 1]; + a0 = d0; a1 = d1; + d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); + d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); + recon[i + 0] = d0; + recon[i + 1] = d1; + } + } else if(bytewidth == 1) { + unsigned char a, b = 0, c, d = 0; + for(i = 0; i != length; ++i) { + c = b; + b = precon[i]; + a = d; + d = scanline[i] + paethPredictor(a, b, c); + recon[i] = d; + } + } else { + /* Normally not a possible case, but this would handle it correctly */ + for(i = 0; i != bytewidth; ++i) { + recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/ + } + } + /* finish any remaining bytes */ + for(; i != length; ++i) { + recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); + } + } else { + size_t j = 0; + for(i = 0; i != bytewidth; ++i) { + recon[i] = scanline[i]; + } + for(i = bytewidth; i != length; ++i, ++j) { + /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/ + recon[i] = (scanline[i] + recon[j]); + } + } + break; + default: return 36; /*error: invalid filter type given*/ + } + return 0; +} + +static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { + /* + For PNG filter method 0 + this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times) + out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline + w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel + in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes) + */ + + unsigned y; + unsigned char* prevline = 0; + + /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ + size_t bytewidth = (bpp + 7u) / 8u; + /*the width of a scanline in bytes, not including the filter type*/ + size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; + + for(y = 0; y < h; ++y) { + size_t outindex = linebytes * y; + size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + unsigned char filterType = in[inindex]; + + CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes)); + + prevline = &out[outindex]; + } + + return 0; +} + +/* +in: Adam7 interlaced image, with no padding bits between scanlines, but between + reduced images so that each reduced image starts at a byte. +out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h +bpp: bits per pixel +out has the following size in bits: w * h * bpp. +in is possibly bigger due to padding bits between reduced images. +out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation +(because that's likely a little bit faster) +NOTE: comments about padding bits are only relevant if bpp < 8 +*/ +static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + if(bpp >= 8) { + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + size_t bytewidth = bpp / 8u; + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth; + size_t pixeloutstart = ((ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * (size_t)w + + ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bytewidth; + for(b = 0; b < bytewidth; ++b) { + out[pixeloutstart + b] = in[pixelinstart + b]; + } + } + } + } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ { + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + unsigned ilinebits = bpp * passw[i]; + unsigned olinebits = bpp * w; + size_t obp, ibp; /*bit pointers (for out and in buffer)*/ + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp); + obp = (ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bpp; + for(b = 0; b < bpp; ++b) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + } + } + } +} + +static void removePaddingBits(unsigned char* out, const unsigned char* in, + size_t olinebits, size_t ilinebits, unsigned h) { + /* + After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need + to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers + for the Adam7 code, the color convert code and the output to the user. + in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must + have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits + also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7 + only useful if (ilinebits - olinebits) is a value in the range 1..7 + */ + unsigned y; + size_t diff = ilinebits - olinebits; + size_t ibp = 0, obp = 0; /*input and output bit pointers*/ + for(y = 0; y < h; ++y) { + size_t x; + for(x = 0; x < olinebits; ++x) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + ibp += diff; + } +} + +/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from +the IDAT chunks (with filter index bytes and possible padding bits) +return value is error*/ +static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, + unsigned w, unsigned h, const LodePNGInfo* info_png) { + /* + This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. + Steps: + *) if no Adam7: 1) unfilter 2) remove padding bits (= possible extra bits per scanline if bpp < 8) + *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace + NOTE: the in buffer will be overwritten with intermediate data! + */ + unsigned bpp = lodepng_get_bpp(&info_png->color); + if(bpp == 0) return 31; /*error: invalid colortype*/ + + if(info_png->interlace_method == 0) { + if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) { + CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp)); + removePaddingBits(out, in, w * bpp, ((w * bpp + 7u) / 8u) * 8u, h); + } + /*we can immediately filter into the out buffer, no other steps needed*/ + else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp)); + } else /*interlace_method is 1 (Adam7)*/ { + unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + for(i = 0; i != 7; ++i) { + CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp)); + /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, + move bytes instead of bits or move not at all*/ + if(bpp < 8) { + /*remove padding bits in scanlines; after this there still may be padding + bits between the different reduced images: each reduced image still starts nicely at a byte*/ + removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, + ((passw[i] * bpp + 7u) / 8u) * 8u, passh[i]); + } + } + + Adam7_deinterlace(out, in, w, h, bpp); + } + + return 0; +} + +static unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) { + unsigned pos = 0, i; + color->palettesize = chunkLength / 3u; + if(color->palettesize == 0 || color->palettesize > 256) return 38; /*error: palette too small or big*/ + lodepng_color_mode_alloc_palette(color); + if(!color->palette && color->palettesize) { + color->palettesize = 0; + return 83; /*alloc fail*/ + } + + for(i = 0; i != color->palettesize; ++i) { + color->palette[4 * i + 0] = data[pos++]; /*R*/ + color->palette[4 * i + 1] = data[pos++]; /*G*/ + color->palette[4 * i + 2] = data[pos++]; /*B*/ + color->palette[4 * i + 3] = 255; /*alpha*/ + } + + return 0; /* OK */ +} + +static unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) { + unsigned i; + if(color->colortype == LCT_PALETTE) { + /*error: more alpha values given than there are palette entries*/ + if(chunkLength > color->palettesize) return 39; + + for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i]; + } else if(color->colortype == LCT_GREY) { + /*error: this chunk must be 2 bytes for grayscale image*/ + if(chunkLength != 2) return 30; + + color->key_defined = 1; + color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1]; + } else if(color->colortype == LCT_RGB) { + /*error: this chunk must be 6 bytes for RGB image*/ + if(chunkLength != 6) return 41; + + color->key_defined = 1; + color->key_r = 256u * data[0] + data[1]; + color->key_g = 256u * data[2] + data[3]; + color->key_b = 256u * data[4] + data[5]; + } + else return 42; /*error: tRNS chunk not allowed for other color models*/ + + return 0; /* OK */ +} + + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*background color chunk (bKGD)*/ +static unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(info->color.colortype == LCT_PALETTE) { + /*error: this chunk must be 1 byte for indexed color image*/ + if(chunkLength != 1) return 43; + + /*error: invalid palette index, or maybe this chunk appeared before PLTE*/ + if(data[0] >= info->color.palettesize) return 103; + + info->background_defined = 1; + info->background_r = info->background_g = info->background_b = data[0]; + } else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { + /*error: this chunk must be 2 bytes for grayscale image*/ + if(chunkLength != 2) return 44; + + /*the values are truncated to bitdepth in the PNG file*/ + info->background_defined = 1; + info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1]; + } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { + /*error: this chunk must be 6 bytes for grayscale image*/ + if(chunkLength != 6) return 45; + + /*the values are truncated to bitdepth in the PNG file*/ + info->background_defined = 1; + info->background_r = 256u * data[0] + data[1]; + info->background_g = 256u * data[2] + data[3]; + info->background_b = 256u * data[4] + data[5]; + } + + return 0; /* OK */ +} + +/*text chunk (tEXt)*/ +static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + unsigned error = 0; + char *key = 0, *str = 0; + + while(!error) /*not really a while loop, only used to break on error*/ { + unsigned length, string2_begin; + + length = 0; + while(length < chunkLength && data[length] != 0) ++length; + /*even though it's not allowed by the standard, no error is thrown if + there's no null termination char, if the text is empty*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(key, data, length); + key[length] = 0; + + string2_begin = length + 1; /*skip keyword null terminator*/ + + length = (unsigned)(chunkLength < string2_begin ? 0 : chunkLength - string2_begin); + str = (char*)lodepng_malloc(length + 1); + if(!str) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(str, data + string2_begin, length); + str[length] = 0; + + error = lodepng_add_text(info, key, str); + + break; + } + + lodepng_free(key); + lodepng_free(str); + + return error; +} + +/*compressed text chunk (zTXt)*/ +static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, + const unsigned char* data, size_t chunkLength) { + unsigned error = 0; + + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + + unsigned length, string2_begin; + char *key = 0; + unsigned char* str = 0; + size_t size = 0; + + while(!error) /*not really a while loop, only used to break on error*/ { + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(key, data, length); + key[length] = 0; + + if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ + + string2_begin = length + 2; + if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ + + length = (unsigned)chunkLength - string2_begin; + zlibsettings.max_output_size = decoder->max_text_size; + /*will fail if zlib error, e.g. if length is too small*/ + error = zlib_decompress(&str, &size, 0, &data[string2_begin], + length, &zlibsettings); + /*error: compressed text larger than decoder->max_text_size*/ + if(error && size > zlibsettings.max_output_size) error = 112; + if(error) break; + error = lodepng_add_text_sized(info, key, (char*)str, size); + break; + } + + lodepng_free(key); + lodepng_free(str); + + return error; +} + +/*international text chunk (iTXt)*/ +static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, + const unsigned char* data, size_t chunkLength) { + unsigned error = 0; + unsigned i; + + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + + unsigned length, begin, compressed; + char *key = 0, *langtag = 0, *transkey = 0; + + while(!error) /*not really a while loop, only used to break on error*/ { + /*Quick check if the chunk length isn't too small. Even without check + it'd still fail with other error checks below if it's too short. This just gives a different error code.*/ + if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/ + + /*read the key*/ + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(key, data, length); + key[length] = 0; + + /*read the compression method*/ + compressed = data[length + 1]; + if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ + + /*even though it's not allowed by the standard, no error is thrown if + there's no null termination char, if the text is empty for the next 3 texts*/ + + /*read the langtag*/ + begin = length + 3; + length = 0; + for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; + + langtag = (char*)lodepng_malloc(length + 1); + if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(langtag, data + begin, length); + langtag[length] = 0; + + /*read the transkey*/ + begin += length + 1; + length = 0; + for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; + + transkey = (char*)lodepng_malloc(length + 1); + if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(transkey, data + begin, length); + transkey[length] = 0; + + /*read the actual text*/ + begin += length + 1; + + length = (unsigned)chunkLength < begin ? 0 : (unsigned)chunkLength - begin; + + if(compressed) { + unsigned char* str = 0; + size_t size = 0; + zlibsettings.max_output_size = decoder->max_text_size; + /*will fail if zlib error, e.g. if length is too small*/ + error = zlib_decompress(&str, &size, 0, &data[begin], + length, &zlibsettings); + /*error: compressed text larger than decoder->max_text_size*/ + if(error && size > zlibsettings.max_output_size) error = 112; + if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size); + lodepng_free(str); + } else { + error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)(data + begin), length); + } + + break; + } + + lodepng_free(key); + lodepng_free(langtag); + lodepng_free(transkey); + + return error; +} + +static unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 7) return 73; /*invalid tIME chunk size*/ + + info->time_defined = 1; + info->time.year = 256u * data[0] + data[1]; + info->time.month = data[2]; + info->time.day = data[3]; + info->time.hour = data[4]; + info->time.minute = data[5]; + info->time.second = data[6]; + + return 0; /* OK */ +} + +static unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/ + + info->phys_defined = 1; + info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; + info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7]; + info->phys_unit = data[8]; + + return 0; /* OK */ +} + +static unsigned readChunk_gAMA(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 4) return 96; /*invalid gAMA chunk size*/ + + info->gama_defined = 1; + info->gama_gamma = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; + + return 0; /* OK */ +} + +static unsigned readChunk_cHRM(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 32) return 97; /*invalid cHRM chunk size*/ + + info->chrm_defined = 1; + info->chrm_white_x = 16777216u * data[ 0] + 65536u * data[ 1] + 256u * data[ 2] + data[ 3]; + info->chrm_white_y = 16777216u * data[ 4] + 65536u * data[ 5] + 256u * data[ 6] + data[ 7]; + info->chrm_red_x = 16777216u * data[ 8] + 65536u * data[ 9] + 256u * data[10] + data[11]; + info->chrm_red_y = 16777216u * data[12] + 65536u * data[13] + 256u * data[14] + data[15]; + info->chrm_green_x = 16777216u * data[16] + 65536u * data[17] + 256u * data[18] + data[19]; + info->chrm_green_y = 16777216u * data[20] + 65536u * data[21] + 256u * data[22] + data[23]; + info->chrm_blue_x = 16777216u * data[24] + 65536u * data[25] + 256u * data[26] + data[27]; + info->chrm_blue_y = 16777216u * data[28] + 65536u * data[29] + 256u * data[30] + data[31]; + + return 0; /* OK */ +} + +static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + if(chunkLength != 1) return 98; /*invalid sRGB chunk size (this one is never ignored)*/ + + info->srgb_defined = 1; + info->srgb_intent = data[0]; + + return 0; /* OK */ +} + +static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, + const unsigned char* data, size_t chunkLength) { + unsigned error = 0; + unsigned i; + size_t size = 0; + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + + unsigned length, string2_begin; + + info->iccp_defined = 1; + if(info->iccp_name) lodepng_clear_icc(info); + + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 2 >= chunkLength) return 75; /*no null termination, corrupt?*/ + if(length < 1 || length > 79) return 89; /*keyword too short or long*/ + + info->iccp_name = (char*)lodepng_malloc(length + 1); + if(!info->iccp_name) return 83; /*alloc fail*/ + + info->iccp_name[length] = 0; + for(i = 0; i != length; ++i) info->iccp_name[i] = (char)data[i]; + + if(data[length + 1] != 0) return 72; /*the 0 byte indicating compression must be 0*/ + + string2_begin = length + 2; + if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/ + + length = (unsigned)chunkLength - string2_begin; + zlibsettings.max_output_size = decoder->max_icc_size; + error = zlib_decompress(&info->iccp_profile, &size, 0, + &data[string2_begin], + length, &zlibsettings); + /*error: ICC profile larger than decoder->max_icc_size*/ + if(error && size > zlibsettings.max_output_size) error = 113; + info->iccp_profile_size = size; + if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/ + return error; +} + +/*significant bits chunk (sBIT)*/ +static unsigned readChunk_sBIT(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { + unsigned bitdepth = (info->color.colortype == LCT_PALETTE) ? 8 : info->color.bitdepth; + if(info->color.colortype == LCT_GREY) { + /*error: this chunk must be 1 bytes for grayscale image*/ + if(chunkLength != 1) return 114; + if(data[0] == 0 || data[0] > bitdepth) return 115; + info->sbit_defined = 1; + info->sbit_r = info->sbit_g = info->sbit_b = data[0]; /*setting g and b is not required, but sensible*/ + } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_PALETTE) { + /*error: this chunk must be 3 bytes for RGB and palette image*/ + if(chunkLength != 3) return 114; + if(data[0] == 0 || data[1] == 0 || data[2] == 0) return 115; + if(data[0] > bitdepth || data[1] > bitdepth || data[2] > bitdepth) return 115; + info->sbit_defined = 1; + info->sbit_r = data[0]; + info->sbit_g = data[1]; + info->sbit_b = data[2]; + } else if(info->color.colortype == LCT_GREY_ALPHA) { + /*error: this chunk must be 2 byte for grayscale with alpha image*/ + if(chunkLength != 2) return 114; + if(data[0] == 0 || data[1] == 0) return 115; + if(data[0] > bitdepth || data[1] > bitdepth) return 115; + info->sbit_defined = 1; + info->sbit_r = info->sbit_g = info->sbit_b = data[0]; /*setting g and b is not required, but sensible*/ + info->sbit_a = data[1]; + } else if(info->color.colortype == LCT_RGBA) { + /*error: this chunk must be 4 bytes for grayscale image*/ + if(chunkLength != 4) return 114; + if(data[0] == 0 || data[1] == 0 || data[2] == 0 || data[3] == 0) return 115; + if(data[0] > bitdepth || data[1] > bitdepth || data[2] > bitdepth || data[3] > bitdepth) return 115; + info->sbit_defined = 1; + info->sbit_r = data[0]; + info->sbit_g = data[1]; + info->sbit_b = data[2]; + info->sbit_a = data[3]; + } + + return 0; /* OK */ +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, + const unsigned char* in, size_t insize) { + const unsigned char* chunk = in + pos; + unsigned chunkLength; + const unsigned char* data; + unsigned unhandled = 0; + unsigned error = 0; + + if(pos + 4 > insize) return 30; + chunkLength = lodepng_chunk_length(chunk); + if(chunkLength > 2147483647) return 63; + data = lodepng_chunk_data_const(chunk); + if(chunkLength + 12 > insize - pos) return 30; + + if(lodepng_chunk_type_equals(chunk, "PLTE")) { + error = readChunk_PLTE(&state->info_png.color, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "tRNS")) { + error = readChunk_tRNS(&state->info_png.color, data, chunkLength); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + } else if(lodepng_chunk_type_equals(chunk, "bKGD")) { + error = readChunk_bKGD(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "tEXt")) { + error = readChunk_tEXt(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "zTXt")) { + error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "iTXt")) { + error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "tIME")) { + error = readChunk_tIME(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "pHYs")) { + error = readChunk_pHYs(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "gAMA")) { + error = readChunk_gAMA(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "cHRM")) { + error = readChunk_cHRM(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "sRGB")) { + error = readChunk_sRGB(&state->info_png, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "iCCP")) { + error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); + } else if(lodepng_chunk_type_equals(chunk, "sBIT")) { + error = readChunk_sBIT(&state->info_png, data, chunkLength); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } else { + /* unhandled chunk is ok (is not an error) */ + unhandled = 1; + } + + if(!error && !unhandled && !state->decoder.ignore_crc) { + if(lodepng_chunk_check_crc(chunk)) return 57; /*invalid CRC*/ + } + + return error; +} + +/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ +static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize) { + unsigned char IEND = 0; + const unsigned char* chunk; /*points to beginning of next chunk*/ + unsigned char* idat; /*the data from idat chunks, zlib compressed*/ + size_t idatsize = 0; + unsigned char* scanlines = 0; + size_t scanlines_size = 0, expected_size = 0; + size_t outsize = 0; + + /*for unknown chunk order*/ + unsigned unknown = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + + + /* safe output values in case error happens */ + *out = 0; + *w = *h = 0; + + state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ + if(state->error) return; + + if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) { + CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/ + } + + /*the input filesize is a safe upper bound for the sum of idat chunks size*/ + idat = (unsigned char*)lodepng_malloc(insize); + if(!idat) CERROR_RETURN(state->error, 83); /*alloc fail*/ + + chunk = &in[33]; /*first byte of the first chunk after the header*/ + + /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. + IDAT data is put at the start of the in buffer*/ + while(!IEND && !state->error) { + unsigned chunkLength; + const unsigned char* data; /*the data in the chunk*/ + size_t pos = (size_t)(chunk - in); + + /*error: next chunk out of bounds of the in buffer*/ + if(chunk < in || pos + 12 > insize) { + if(state->decoder.ignore_end) break; /*other errors may still happen though*/ + CERROR_BREAK(state->error, 30); + } + + /*length of the data of the chunk, excluding the 12 bytes for length, chunk type and CRC*/ + chunkLength = lodepng_chunk_length(chunk); + /*error: chunk length larger than the max PNG chunk size*/ + if(chunkLength > 2147483647) { + if(state->decoder.ignore_end) break; /*other errors may still happen though*/ + CERROR_BREAK(state->error, 63); + } + + if(pos + (size_t)chunkLength + 12 > insize || pos + (size_t)chunkLength + 12 < pos) { + CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk (or int overflow)*/ + } + + data = lodepng_chunk_data_const(chunk); + + unknown = 0; + + /*IDAT chunk, containing compressed image data*/ + if(lodepng_chunk_type_equals(chunk, "IDAT")) { + size_t newsize; + if(lodepng_addofl(idatsize, chunkLength, &newsize)) CERROR_BREAK(state->error, 95); + if(newsize > insize) CERROR_BREAK(state->error, 95); + lodepng_memcpy(idat + idatsize, data, chunkLength); + idatsize += chunkLength; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + critical_pos = 3; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } else if(lodepng_chunk_type_equals(chunk, "IEND")) { + /*IEND chunk*/ + IEND = 1; + } else if(lodepng_chunk_type_equals(chunk, "PLTE")) { + /*palette chunk (PLTE)*/ + state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength); + if(state->error) break; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + critical_pos = 2; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } else if(lodepng_chunk_type_equals(chunk, "tRNS")) { + /*palette transparency chunk (tRNS). Even though this one is an ancillary chunk , it is still compiled + in without 'LODEPNG_COMPILE_ANCILLARY_CHUNKS' because it contains essential color information that + affects the alpha channel of pixels. */ + state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength); + if(state->error) break; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*background color chunk (bKGD)*/ + } else if(lodepng_chunk_type_equals(chunk, "bKGD")) { + state->error = readChunk_bKGD(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "tEXt")) { + /*text chunk (tEXt)*/ + if(state->decoder.read_text_chunks) { + state->error = readChunk_tEXt(&state->info_png, data, chunkLength); + if(state->error) break; + } + } else if(lodepng_chunk_type_equals(chunk, "zTXt")) { + /*compressed text chunk (zTXt)*/ + if(state->decoder.read_text_chunks) { + state->error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); + if(state->error) break; + } + } else if(lodepng_chunk_type_equals(chunk, "iTXt")) { + /*international text chunk (iTXt)*/ + if(state->decoder.read_text_chunks) { + state->error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); + if(state->error) break; + } + } else if(lodepng_chunk_type_equals(chunk, "tIME")) { + state->error = readChunk_tIME(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "pHYs")) { + state->error = readChunk_pHYs(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "gAMA")) { + state->error = readChunk_gAMA(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "cHRM")) { + state->error = readChunk_cHRM(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "sRGB")) { + state->error = readChunk_sRGB(&state->info_png, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "iCCP")) { + state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); + if(state->error) break; + } else if(lodepng_chunk_type_equals(chunk, "sBIT")) { + state->error = readChunk_sBIT(&state->info_png, data, chunkLength); + if(state->error) break; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } else /*it's not an implemented chunk type, so ignore it: skip over the data*/ { + /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ + if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk)) { + CERROR_BREAK(state->error, 69); + } + + unknown = 1; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(state->decoder.remember_unknown_chunks) { + state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1], + &state->info_png.unknown_chunks_size[critical_pos - 1], chunk); + if(state->error) break; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + + if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/ { + if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/ + } + + if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize); + } + + if(!state->error && state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) { + state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */ + } + + if(!state->error) { + /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation. + If the decompressed size does not match the prediction, the image must be corrupt.*/ + if(state->info_png.interlace_method == 0) { + size_t bpp = lodepng_get_bpp(&state->info_png.color); + expected_size = lodepng_get_raw_size_idat(*w, *h, bpp); + } else { + size_t bpp = lodepng_get_bpp(&state->info_png.color); + /*Adam-7 interlaced: expected size is the sum of the 7 sub-images sizes*/ + expected_size = 0; + expected_size += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, bpp); + if(*w > 4) expected_size += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, bpp); + expected_size += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, bpp); + if(*w > 2) expected_size += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, bpp); + expected_size += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, bpp); + if(*w > 1) expected_size += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, bpp); + expected_size += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, bpp); + } + + state->error = zlib_decompress(&scanlines, &scanlines_size, expected_size, idat, idatsize, &state->decoder.zlibsettings); + } + if(!state->error && scanlines_size != expected_size) state->error = 91; /*decompressed size doesn't match prediction*/ + lodepng_free(idat); + + if(!state->error) { + outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color); + *out = (unsigned char*)lodepng_malloc(outsize); + if(!*out) state->error = 83; /*alloc fail*/ + } + if(!state->error) { + lodepng_memset(*out, 0, outsize); + state->error = postProcessScanlines(*out, scanlines, *w, *h, &state->info_png); + } + lodepng_free(scanlines); +} + +unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize) { + *out = 0; + decodeGeneric(out, w, h, state, in, insize); + if(state->error) return state->error; + if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) { + /*same color type, no copying or converting of data needed*/ + /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype + the raw image has to the end user*/ + if(!state->decoder.color_convert) { + state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color); + if(state->error) return state->error; + } + } else { /*color conversion needed*/ + unsigned char* data = *out; + size_t outsize; + + /*TODO: check if this works according to the statement in the documentation: "The converter can convert + from grayscale input color type, to 8-bit grayscale or grayscale with alpha"*/ + if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA) + && !(state->info_raw.bitdepth == 8)) { + return 56; /*unsupported color mode conversion*/ + } + + outsize = lodepng_get_raw_size(*w, *h, &state->info_raw); + *out = (unsigned char*)lodepng_malloc(outsize); + if(!(*out)) { + state->error = 83; /*alloc fail*/ + } + else state->error = lodepng_convert(*out, data, &state->info_raw, + &state->info_png.color, *w, *h); + lodepng_free(data); + } + return state->error; +} + +unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, + size_t insize, LodePNGColorType colortype, unsigned bitdepth) { + unsigned error; + LodePNGState state; + lodepng_state_init(&state); + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*disable reading things that this function doesn't output*/ + state.decoder.read_text_chunks = 0; + state.decoder.remember_unknown_chunks = 0; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + error = lodepng_decode(out, w, h, &state, in, insize); + lodepng_state_cleanup(&state); + return error; +} + +unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) { + return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8); +} + +unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) { + return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename, + LodePNGColorType colortype, unsigned bitdepth) { + unsigned char* buffer = 0; + size_t buffersize; + unsigned error; + /* safe output values in case error happens */ + *out = 0; + *w = *h = 0; + error = lodepng_load_file(&buffer, &buffersize, filename); + if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth); + lodepng_free(buffer); + return error; +} + +unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) { + return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8); +} + +unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) { + return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8); +} +#endif /*LODEPNG_COMPILE_DISK*/ + +void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) { + settings->color_convert = 1; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + settings->read_text_chunks = 1; + settings->remember_unknown_chunks = 0; + settings->max_text_size = 16777216; + settings->max_icc_size = 16777216; /* 16MB is much more than enough for any reasonable ICC profile */ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + settings->ignore_crc = 0; + settings->ignore_critical = 0; + settings->ignore_end = 0; + lodepng_decompress_settings_init(&settings->zlibsettings); +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) + +void lodepng_state_init(LodePNGState* state) { +#ifdef LODEPNG_COMPILE_DECODER + lodepng_decoder_settings_init(&state->decoder); +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER + lodepng_encoder_settings_init(&state->encoder); +#endif /*LODEPNG_COMPILE_ENCODER*/ + lodepng_color_mode_init(&state->info_raw); + lodepng_info_init(&state->info_png); + state->error = 1; +} + +void lodepng_state_cleanup(LodePNGState* state) { + lodepng_color_mode_cleanup(&state->info_raw); + lodepng_info_cleanup(&state->info_png); +} + +void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source) { + lodepng_state_cleanup(dest); + *dest = *source; + lodepng_color_mode_init(&dest->info_raw); + lodepng_info_init(&dest->info_png); + dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return; + dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return; +} + +#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ + +#ifdef LODEPNG_COMPILE_ENCODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG Encoder / */ +/* ////////////////////////////////////////////////////////////////////////// */ + + +static unsigned writeSignature(ucvector* out) { + size_t pos = out->size; + const unsigned char signature[] = {137, 80, 78, 71, 13, 10, 26, 10}; + /*8 bytes PNG signature, aka the magic bytes*/ + if(!ucvector_resize(out, out->size + 8)) return 83; /*alloc fail*/ + lodepng_memcpy(out->data + pos, signature, 8); + return 0; +} + +static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) { + unsigned char *chunk, *data; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 13, "IHDR")); + data = chunk + 8; + + lodepng_set32bitInt(data + 0, w); /*width*/ + lodepng_set32bitInt(data + 4, h); /*height*/ + data[8] = (unsigned char)bitdepth; /*bit depth*/ + data[9] = (unsigned char)colortype; /*color type*/ + data[10] = 0; /*compression method*/ + data[11] = 0; /*filter method*/ + data[12] = interlace_method; /*interlace method*/ + + lodepng_chunk_generate_crc(chunk); + return 0; +} + +/* only adds the chunk if needed (there is a key or palette with alpha) */ +static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) { + unsigned char* chunk; + size_t i, j = 8; + + if(info->palettesize == 0 || info->palettesize > 256) { + return 68; /*invalid palette size, it is only allowed to be 1-256*/ + } + + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, info->palettesize * 3, "PLTE")); + + for(i = 0; i != info->palettesize; ++i) { + /*add all channels except alpha channel*/ + chunk[j++] = info->palette[i * 4 + 0]; + chunk[j++] = info->palette[i * 4 + 1]; + chunk[j++] = info->palette[i * 4 + 2]; + } + + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info) { + unsigned char* chunk = 0; + + if(info->colortype == LCT_PALETTE) { + size_t i, amount = info->palettesize; + /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/ + for(i = info->palettesize; i != 0; --i) { + if(info->palette[4 * (i - 1) + 3] != 255) break; + --amount; + } + if(amount) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, amount, "tRNS")); + /*add the alpha channel values from the palette*/ + for(i = 0; i != amount; ++i) chunk[8 + i] = info->palette[4 * i + 3]; + } + } else if(info->colortype == LCT_GREY) { + if(info->key_defined) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "tRNS")); + chunk[8] = (unsigned char)(info->key_r >> 8); + chunk[9] = (unsigned char)(info->key_r & 255); + } + } else if(info->colortype == LCT_RGB) { + if(info->key_defined) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "tRNS")); + chunk[8] = (unsigned char)(info->key_r >> 8); + chunk[9] = (unsigned char)(info->key_r & 255); + chunk[10] = (unsigned char)(info->key_g >> 8); + chunk[11] = (unsigned char)(info->key_g & 255); + chunk[12] = (unsigned char)(info->key_b >> 8); + chunk[13] = (unsigned char)(info->key_b & 255); + } + } + + if(chunk) lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize, + LodePNGCompressSettings* zlibsettings) { + unsigned error = 0; + unsigned char* zlib = 0; + size_t zlibsize = 0; + + error = zlib_compress(&zlib, &zlibsize, data, datasize, zlibsettings); + if(!error) { + error = lodepng_chunk_createv(out, zlibsize, "IDAT", zlib); + } + lodepng_free(zlib); + return error; +} + +static unsigned addChunk_IEND(ucvector* out) { + return lodepng_chunk_createv(out, 0, "IEND", 0); +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) { + unsigned char* chunk = 0; + size_t keysize = lodepng_strlen(keyword), textsize = lodepng_strlen(textstring); + size_t size = keysize + 1 + textsize; + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, size, "tEXt")); + lodepng_memcpy(chunk + 8, keyword, keysize); + chunk[8 + keysize] = 0; /*null termination char*/ + lodepng_memcpy(chunk + 9 + keysize, textstring, textsize); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring, + LodePNGCompressSettings* zlibsettings) { + unsigned error = 0; + unsigned char* chunk = 0; + unsigned char* compressed = 0; + size_t compressedsize = 0; + size_t textsize = lodepng_strlen(textstring); + size_t keysize = lodepng_strlen(keyword); + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + + error = zlib_compress(&compressed, &compressedsize, + (const unsigned char*)textstring, textsize, zlibsettings); + if(!error) { + size_t size = keysize + 2 + compressedsize; + error = lodepng_chunk_init(&chunk, out, size, "zTXt"); + } + if(!error) { + lodepng_memcpy(chunk + 8, keyword, keysize); + chunk[8 + keysize] = 0; /*null termination char*/ + chunk[9 + keysize] = 0; /*compression method: 0*/ + lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize); + lodepng_chunk_generate_crc(chunk); + } + + lodepng_free(compressed); + return error; +} + +static unsigned addChunk_iTXt(ucvector* out, unsigned compress, const char* keyword, const char* langtag, + const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings) { + unsigned error = 0; + unsigned char* chunk = 0; + unsigned char* compressed = 0; + size_t compressedsize = 0; + size_t textsize = lodepng_strlen(textstring); + size_t keysize = lodepng_strlen(keyword), langsize = lodepng_strlen(langtag), transsize = lodepng_strlen(transkey); + + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + + if(compress) { + error = zlib_compress(&compressed, &compressedsize, + (const unsigned char*)textstring, textsize, zlibsettings); + } + if(!error) { + size_t size = keysize + 3 + langsize + 1 + transsize + 1 + (compress ? compressedsize : textsize); + error = lodepng_chunk_init(&chunk, out, size, "iTXt"); + } + if(!error) { + size_t pos = 8; + lodepng_memcpy(chunk + pos, keyword, keysize); + pos += keysize; + chunk[pos++] = 0; /*null termination char*/ + chunk[pos++] = (compress ? 1 : 0); /*compression flag*/ + chunk[pos++] = 0; /*compression method: 0*/ + lodepng_memcpy(chunk + pos, langtag, langsize); + pos += langsize; + chunk[pos++] = 0; /*null termination char*/ + lodepng_memcpy(chunk + pos, transkey, transsize); + pos += transsize; + chunk[pos++] = 0; /*null termination char*/ + if(compress) { + lodepng_memcpy(chunk + pos, compressed, compressedsize); + } else { + lodepng_memcpy(chunk + pos, textstring, textsize); + } + lodepng_chunk_generate_crc(chunk); + } + + lodepng_free(compressed); + return error; +} + +static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk = 0; + if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "bKGD")); + chunk[8] = (unsigned char)(info->background_r >> 8); + chunk[9] = (unsigned char)(info->background_r & 255); + } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "bKGD")); + chunk[8] = (unsigned char)(info->background_r >> 8); + chunk[9] = (unsigned char)(info->background_r & 255); + chunk[10] = (unsigned char)(info->background_g >> 8); + chunk[11] = (unsigned char)(info->background_g & 255); + chunk[12] = (unsigned char)(info->background_b >> 8); + chunk[13] = (unsigned char)(info->background_b & 255); + } else if(info->color.colortype == LCT_PALETTE) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 1, "bKGD")); + chunk[8] = (unsigned char)(info->background_r & 255); /*palette index*/ + } + if(chunk) lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 7, "tIME")); + chunk[8] = (unsigned char)(time->year >> 8); + chunk[9] = (unsigned char)(time->year & 255); + chunk[10] = (unsigned char)time->month; + chunk[11] = (unsigned char)time->day; + chunk[12] = (unsigned char)time->hour; + chunk[13] = (unsigned char)time->minute; + chunk[14] = (unsigned char)time->second; + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 9, "pHYs")); + lodepng_set32bitInt(chunk + 8, info->phys_x); + lodepng_set32bitInt(chunk + 12, info->phys_y); + chunk[16] = info->phys_unit; + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_gAMA(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "gAMA")); + lodepng_set32bitInt(chunk + 8, info->gama_gamma); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_cHRM(ucvector* out, const LodePNGInfo* info) { + unsigned char* chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 32, "cHRM")); + lodepng_set32bitInt(chunk + 8, info->chrm_white_x); + lodepng_set32bitInt(chunk + 12, info->chrm_white_y); + lodepng_set32bitInt(chunk + 16, info->chrm_red_x); + lodepng_set32bitInt(chunk + 20, info->chrm_red_y); + lodepng_set32bitInt(chunk + 24, info->chrm_green_x); + lodepng_set32bitInt(chunk + 28, info->chrm_green_y); + lodepng_set32bitInt(chunk + 32, info->chrm_blue_x); + lodepng_set32bitInt(chunk + 36, info->chrm_blue_y); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_sRGB(ucvector* out, const LodePNGInfo* info) { + unsigned char data = info->srgb_intent; + return lodepng_chunk_createv(out, 1, "sRGB", &data); +} + +static unsigned addChunk_iCCP(ucvector* out, const LodePNGInfo* info, LodePNGCompressSettings* zlibsettings) { + unsigned error = 0; + unsigned char* chunk = 0; + unsigned char* compressed = 0; + size_t compressedsize = 0; + size_t keysize = lodepng_strlen(info->iccp_name); + + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + error = zlib_compress(&compressed, &compressedsize, + info->iccp_profile, info->iccp_profile_size, zlibsettings); + if(!error) { + size_t size = keysize + 2 + compressedsize; + error = lodepng_chunk_init(&chunk, out, size, "iCCP"); + } + if(!error) { + lodepng_memcpy(chunk + 8, info->iccp_name, keysize); + chunk[8 + keysize] = 0; /*null termination char*/ + chunk[9 + keysize] = 0; /*compression method: 0*/ + lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize); + lodepng_chunk_generate_crc(chunk); + } + + lodepng_free(compressed); + return error; +} + +static unsigned addChunk_sBIT(ucvector* out, const LodePNGInfo* info) { + unsigned bitdepth = (info->color.colortype == LCT_PALETTE) ? 8 : info->color.bitdepth; + unsigned char* chunk = 0; + if(info->color.colortype == LCT_GREY) { + if(info->sbit_r == 0 || info->sbit_r > bitdepth) return 115; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 1, "sBIT")); + chunk[8] = info->sbit_r; + } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_PALETTE) { + if(info->sbit_r == 0 || info->sbit_g == 0 || info->sbit_b == 0) return 115; + if(info->sbit_r > bitdepth || info->sbit_g > bitdepth || info->sbit_b > bitdepth) return 115; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 3, "sBIT")); + chunk[8] = info->sbit_r; + chunk[9] = info->sbit_g; + chunk[10] = info->sbit_b; + } else if(info->color.colortype == LCT_GREY_ALPHA) { + if(info->sbit_r == 0 || info->sbit_a == 0) return 115; + if(info->sbit_r > bitdepth || info->sbit_a > bitdepth) return 115; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "sBIT")); + chunk[8] = info->sbit_r; + chunk[9] = info->sbit_a; + } else if(info->color.colortype == LCT_RGBA) { + if(info->sbit_r == 0 || info->sbit_g == 0 || info->sbit_b == 0 || info->sbit_a == 0 || + info->sbit_r > bitdepth || info->sbit_g > bitdepth || + info->sbit_b > bitdepth || info->sbit_a > bitdepth) { + return 115; + } + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "sBIT")); + chunk[8] = info->sbit_r; + chunk[9] = info->sbit_g; + chunk[10] = info->sbit_b; + chunk[11] = info->sbit_a; + } + if(chunk) lodepng_chunk_generate_crc(chunk); + return 0; +} + +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, + size_t length, size_t bytewidth, unsigned char filterType) { + size_t i; + switch(filterType) { + case 0: /*None*/ + for(i = 0; i != length; ++i) out[i] = scanline[i]; + break; + case 1: /*Sub*/ + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth]; + break; + case 2: /*Up*/ + if(prevline) { + for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i]; + } else { + for(i = 0; i != length; ++i) out[i] = scanline[i]; + } + break; + case 3: /*Average*/ + if(prevline) { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1); + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1); + } else { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1); + } + break; + case 4: /*Paeth*/ + if(prevline) { + /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/ + for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]); + for(i = bytewidth; i < length; ++i) { + out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); + } + } else { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/ + for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]); + } + break; + default: return; /*invalid filter type given*/ + } +} + +/* integer binary logarithm, max return value is 31 */ +static size_t ilog2(size_t i) { + size_t result = 0; + if(i >= 65536) { result += 16; i >>= 16; } + if(i >= 256) { result += 8; i >>= 8; } + if(i >= 16) { result += 4; i >>= 4; } + if(i >= 4) { result += 2; i >>= 2; } + if(i >= 2) { result += 1; /*i >>= 1;*/ } + return result; +} + +/* integer approximation for i * log2(i), helper function for LFS_ENTROPY */ +static size_t ilog2i(size_t i) { + size_t l; + if(i == 0) return 0; + l = ilog2(i); + /* approximate i*log2(i): l is integer logarithm, ((i - (1u << l)) << 1u) + linearly approximates the missing fractional part multiplied by i */ + return i * l + ((i - (1u << l)) << 1u); +} + +static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, + const LodePNGColorMode* color, const LodePNGEncoderSettings* settings) { + /* + For PNG filter method 0 + out must be a buffer with as size: h + (w * h * bpp + 7u) / 8u, because there are + the scanlines with 1 extra byte per scanline + */ + + unsigned bpp = lodepng_get_bpp(color); + /*the width of a scanline in bytes, not including the filter type*/ + size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; + + /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ + size_t bytewidth = (bpp + 7u) / 8u; + const unsigned char* prevline = 0; + unsigned x, y; + unsigned error = 0; + LodePNGFilterStrategy strategy = settings->filter_strategy; + + /* + There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard: + * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. + use fixed filtering, with the filter None). + * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is + not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply + all five filters and select the filter that produces the smallest sum of absolute values per row. + This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true. + + If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed, + but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum + heuristic is used. + */ + if(settings->filter_palette_zero && + (color->colortype == LCT_PALETTE || color->bitdepth < 8)) strategy = LFS_ZERO; + + if(bpp == 0) return 31; /*error: invalid color type*/ + + if(strategy >= LFS_ZERO && strategy <= LFS_FOUR) { + unsigned char type = (unsigned char)strategy; + for(y = 0; y != h; ++y) { + size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + size_t inindex = linebytes * y; + out[outindex] = type; /*filter type byte*/ + filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); + prevline = &in[inindex]; + } + } else if(strategy == LFS_MINSUM) { + /*adaptive filtering*/ + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t smallest = 0; + unsigned char type, bestType = 0; + + for(type = 0; type != 5; ++type) { + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) error = 83; /*alloc fail*/ + } + + if(!error) { + for(y = 0; y != h; ++y) { + /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) { + size_t sum = 0; + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + + /*calculate the sum of the result*/ + if(type == 0) { + for(x = 0; x != linebytes; ++x) sum += (unsigned char)(attempt[type][x]); + } else { + for(x = 0; x != linebytes; ++x) { + /*For differences, each byte should be treated as signed, values above 127 are negative + (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there. + This means filtertype 0 is almost never chosen, but that is justified.*/ + unsigned char s = attempt[type][x]; + sum += s < 128 ? s : (255U - s); + } + } + + /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || sum < smallest) { + bestType = type; + smallest = sum; + } + } + + prevline = &in[y * linebytes]; + + /*now fill the out values*/ + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + } + + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } else if(strategy == LFS_ENTROPY) { + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t bestSum = 0; + unsigned type, bestType = 0; + unsigned count[256]; + + for(type = 0; type != 5; ++type) { + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) error = 83; /*alloc fail*/ + } + + if(!error) { + for(y = 0; y != h; ++y) { + /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) { + size_t sum = 0; + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + lodepng_memset(count, 0, 256 * sizeof(*count)); + for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]]; + ++count[type]; /*the filter type itself is part of the scanline*/ + for(x = 0; x != 256; ++x) { + sum += ilog2i(count[x]); + } + /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || sum > bestSum) { + bestType = type; + bestSum = sum; + } + } + + prevline = &in[y * linebytes]; + + /*now fill the out values*/ + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + } + + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } else if(strategy == LFS_PREDEFINED) { + for(y = 0; y != h; ++y) { + size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + size_t inindex = linebytes * y; + unsigned char type = settings->predefined_filters[y]; + out[outindex] = type; /*filter type byte*/ + filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); + prevline = &in[inindex]; + } + } else if(strategy == LFS_BRUTE_FORCE) { + /*brute force filter chooser. + deflate the scanline after every filter attempt to see which one deflates best. + This is very slow and gives only slightly smaller, sometimes even larger, result*/ + size_t size[5]; + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t smallest = 0; + unsigned type = 0, bestType = 0; + unsigned char* dummy; + LodePNGCompressSettings zlibsettings; + lodepng_memcpy(&zlibsettings, &settings->zlibsettings, sizeof(LodePNGCompressSettings)); + /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, + to simulate the true case where the tree is the same for the whole image. Sometimes it gives + better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare + cases better compression. It does make this a bit less slow, so it's worth doing this.*/ + zlibsettings.btype = 1; + /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG + images only, so disable it*/ + zlibsettings.custom_zlib = 0; + zlibsettings.custom_deflate = 0; + for(type = 0; type != 5; ++type) { + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) error = 83; /*alloc fail*/ + } + if(!error) { + for(y = 0; y != h; ++y) /*try the 5 filter types*/ { + for(type = 0; type != 5; ++type) { + unsigned testsize = (unsigned)linebytes; + /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/ + + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + size[type] = 0; + dummy = 0; + zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings); + lodepng_free(dummy); + /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || size[type] < smallest) { + bestType = type; + smallest = size[type]; + } + } + prevline = &in[y * linebytes]; + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + } + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } + else return 88; /* unknown filter strategy */ + + return error; +} + +static void addPaddingBits(unsigned char* out, const unsigned char* in, + size_t olinebits, size_t ilinebits, unsigned h) { + /*The opposite of the removePaddingBits function + olinebits must be >= ilinebits*/ + unsigned y; + size_t diff = olinebits - ilinebits; + size_t obp = 0, ibp = 0; /*bit pointers*/ + for(y = 0; y != h; ++y) { + size_t x; + for(x = 0; x < ilinebits; ++x) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + /*obp += diff; --> no, fill in some value in the padding bits too, to avoid + "Use of uninitialised value of size ###" warning from valgrind*/ + for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0); + } +} + +/* +in: non-interlaced image with size w*h +out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with + no padding bits between scanlines, but between reduced images so that each + reduced image starts at a byte. +bpp: bits per pixel +there are no padding bits, not between scanlines, not between reduced images +in has the following size in bits: w * h * bpp. +out is possibly bigger due to padding bits between reduced images +NOTE: comments about padding bits are only relevant if bpp < 8 +*/ +static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + if(bpp >= 8) { + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + size_t bytewidth = bpp / 8u; + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; + size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; + for(b = 0; b < bytewidth; ++b) { + out[pixeloutstart + b] = in[pixelinstart + b]; + } + } + } + } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ { + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + unsigned ilinebits = bpp * passw[i]; + unsigned olinebits = bpp * w; + size_t obp, ibp; /*bit pointers (for out and in buffer)*/ + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; + obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); + for(b = 0; b < bpp; ++b) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + } + } + } +} + +/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image. +return value is error**/ +static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in, + unsigned w, unsigned h, + const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings) { + /* + This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: + *) if no Adam7: 1) add padding bits (= possible extra bits per scanline if bpp < 8) 2) filter + *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter + */ + unsigned bpp = lodepng_get_bpp(&info_png->color); + unsigned error = 0; + + if(info_png->interlace_method == 0) { + *outsize = h + (h * ((w * bpp + 7u) / 8u)); /*image size plus an extra byte per scanline + possible padding bits*/ + *out = (unsigned char*)lodepng_malloc(*outsize); + if(!(*out) && (*outsize)) error = 83; /*alloc fail*/ + + if(!error) { + /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ + if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) { + unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7u) / 8u)); + if(!padded) error = 83; /*alloc fail*/ + if(!error) { + addPaddingBits(padded, in, ((w * bpp + 7u) / 8u) * 8u, w * bpp, h); + error = filter(*out, padded, w, h, &info_png->color, settings); + } + lodepng_free(padded); + } else { + /*we can immediately filter into the out buffer, no other steps needed*/ + error = filter(*out, in, w, h, &info_png->color, settings); + } + } + } else /*interlace_method is 1 (Adam7)*/ { + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned char* adam7; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ + *out = (unsigned char*)lodepng_malloc(*outsize); + if(!(*out)) error = 83; /*alloc fail*/ + + adam7 = (unsigned char*)lodepng_malloc(passstart[7]); + if(!adam7 && passstart[7]) error = 83; /*alloc fail*/ + + if(!error) { + unsigned i; + + Adam7_interlace(adam7, in, w, h, bpp); + for(i = 0; i != 7; ++i) { + if(bpp < 8) { + unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]); + if(!padded) ERROR_BREAK(83); /*alloc fail*/ + addPaddingBits(padded, &adam7[passstart[i]], + ((passw[i] * bpp + 7u) / 8u) * 8u, passw[i] * bpp, passh[i]); + error = filter(&(*out)[filter_passstart[i]], padded, + passw[i], passh[i], &info_png->color, settings); + lodepng_free(padded); + } else { + error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], + passw[i], passh[i], &info_png->color, settings); + } + + if(error) break; + } + } + + lodepng_free(adam7); + } + + return error; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) { + unsigned char* inchunk = data; + while((size_t)(inchunk - data) < datasize) { + CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk)); + out->allocsize = out->size; /*fix the allocsize again*/ + inchunk = lodepng_chunk_next(inchunk, data + datasize); + } + return 0; +} + +static unsigned isGrayICCProfile(const unsigned char* profile, unsigned size) { + /* + It is a gray profile if bytes 16-19 are "GRAY", rgb profile if bytes 16-19 + are "RGB ". We do not perform any full parsing of the ICC profile here, other + than check those 4 bytes to grayscale profile. Other than that, validity of + the profile is not checked. This is needed only because the PNG specification + requires using a non-gray color model if there is an ICC profile with "RGB " + (sadly limiting compression opportunities if the input data is grayscale RGB + data), and requires using a gray color model if it is "GRAY". + */ + if(size < 20) return 0; + return profile[16] == 'G' && profile[17] == 'R' && profile[18] == 'A' && profile[19] == 'Y'; +} + +static unsigned isRGBICCProfile(const unsigned char* profile, unsigned size) { + /* See comment in isGrayICCProfile*/ + if(size < 20) return 0; + return profile[16] == 'R' && profile[17] == 'G' && profile[18] == 'B' && profile[19] == ' '; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +unsigned lodepng_encode(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGState* state) { + unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ + size_t datasize = 0; + ucvector outv = ucvector_init(NULL, 0); + LodePNGInfo info; + const LodePNGInfo* info_png = &state->info_png; + LodePNGColorMode auto_color; + + lodepng_info_init(&info); + lodepng_color_mode_init(&auto_color); + + /*provide some proper output values if error will happen*/ + *out = 0; + *outsize = 0; + state->error = 0; + + /*check input values validity*/ + if((info_png->color.colortype == LCT_PALETTE || state->encoder.force_palette) + && (info_png->color.palettesize == 0 || info_png->color.palettesize > 256)) { + /*this error is returned even if auto_convert is enabled and thus encoder could + generate the palette by itself: while allowing this could be possible in theory, + it may complicate the code or edge cases, and always requiring to give a palette + when setting this color type is a simpler contract*/ + state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/ + goto cleanup; + } + if(state->encoder.zlibsettings.btype > 2) { + state->error = 61; /*error: invalid btype*/ + goto cleanup; + } + if(info_png->interlace_method > 1) { + state->error = 71; /*error: invalid interlace mode*/ + goto cleanup; + } + state->error = checkColorValidity(info_png->color.colortype, info_png->color.bitdepth); + if(state->error) goto cleanup; /*error: invalid color type given*/ + state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth); + if(state->error) goto cleanup; /*error: invalid color type given*/ + + /* color convert and compute scanline filter types */ + lodepng_info_copy(&info, &state->info_png); + if(state->encoder.auto_convert) { + LodePNGColorStats stats; + unsigned allow_convert = 1; + lodepng_color_stats_init(&stats); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->iccp_defined && + isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) { + /*the PNG specification does not allow to use palette with a GRAY ICC profile, even + if the palette has only gray colors, so disallow it.*/ + stats.allow_palette = 0; + } + if(info_png->iccp_defined && + isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) { + /*the PNG specification does not allow to use grayscale color with RGB ICC profile, so disallow gray.*/ + stats.allow_greyscale = 0; + } +#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ + state->error = lodepng_compute_color_stats(&stats, image, w, h, &state->info_raw); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->background_defined) { + /*the background chunk's color must be taken into account as well*/ + unsigned r = 0, g = 0, b = 0; + LodePNGColorMode mode16 = lodepng_color_mode_make(LCT_RGB, 16); + lodepng_convert_rgb(&r, &g, &b, + info_png->background_r, info_png->background_g, info_png->background_b, &mode16, &info_png->color); + state->error = lodepng_color_stats_add(&stats, r, g, b, 65535); + if(state->error) goto cleanup; + } +#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ + state->error = auto_choose_color(&auto_color, &state->info_raw, &stats); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->sbit_defined) { + /*if sbit is defined, due to strict requirements of which sbit values can be present for which color modes, + auto_convert can't be done in many cases. However, do support a few cases here. + TODO: more conversions may be possible, and it may also be possible to get a more appropriate color type out of + auto_choose_color if knowledge about sbit is used beforehand + */ + unsigned sbit_max = LODEPNG_MAX(LODEPNG_MAX(LODEPNG_MAX(info_png->sbit_r, info_png->sbit_g), + info_png->sbit_b), info_png->sbit_a); + unsigned equal = (!info_png->sbit_g || info_png->sbit_g == info_png->sbit_r) + && (!info_png->sbit_b || info_png->sbit_b == info_png->sbit_r) + && (!info_png->sbit_a || info_png->sbit_a == info_png->sbit_r); + allow_convert = 0; + if(info.color.colortype == LCT_PALETTE && + auto_color.colortype == LCT_PALETTE) { + /* input and output are palette, and in this case it may happen that palette data is + expected to be copied from info_raw into the info_png */ + allow_convert = 1; + } + /*going from 8-bit RGB to palette (or 16-bit as long as sbit_max <= 8) is possible + since both are 8-bit RGB for sBIT's purposes*/ + if(info.color.colortype == LCT_RGB && + auto_color.colortype == LCT_PALETTE && sbit_max <= 8) { + allow_convert = 1; + } + /*going from 8-bit RGBA to palette is also ok but only if sbit_a is exactly 8*/ + if(info.color.colortype == LCT_RGBA && auto_color.colortype == LCT_PALETTE && + info_png->sbit_a == 8 && sbit_max <= 8) { + allow_convert = 1; + } + /*going from 16-bit RGB(A) to 8-bit RGB(A) is ok if all sbit values are <= 8*/ + if((info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA) && info.color.bitdepth == 16 && + auto_color.colortype == info.color.colortype && auto_color.bitdepth == 8 && + sbit_max <= 8) { + allow_convert = 1; + } + /*going to less channels is ok if all bit values are equal (all possible values in sbit, + as well as the chosen bitdepth of the result). Due to how auto_convert works, + we already know that auto_color.colortype has less than or equal amount of channels than + info.colortype. Palette is not used here. This conversion is not allowed if + info_png->sbit_r < auto_color.bitdepth, because specifically for alpha, non-presence of + an sbit value heavily implies that alpha's bit depth is equal to the PNG bit depth (rather + than the bit depths set in the r, g and b sbit values, by how the PNG specification describes + handling tRNS chunk case with sBIT), so be conservative here about ignoring user input.*/ + if(info.color.colortype != LCT_PALETTE && auto_color.colortype != LCT_PALETTE && + equal && info_png->sbit_r == auto_color.bitdepth) { + allow_convert = 1; + } + } +#endif + if(state->encoder.force_palette) { + if(info.color.colortype != LCT_GREY && info.color.colortype != LCT_GREY_ALPHA && + (auto_color.colortype == LCT_GREY || auto_color.colortype == LCT_GREY_ALPHA)) { + /*user speficially forced a PLTE palette, so cannot convert to grayscale types because + the PNG specification only allows writing a suggested palette in PLTE for truecolor types*/ + allow_convert = 0; + } + } + if(allow_convert) { + lodepng_color_mode_copy(&info.color, &auto_color); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*also convert the background chunk*/ + if(info_png->background_defined) { + if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b, + info_png->background_r, info_png->background_g, info_png->background_b, &info.color, &info_png->color)) { + state->error = 104; + goto cleanup; + } + } +#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ + } + } +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->iccp_defined) { + unsigned gray_icc = isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size); + unsigned rgb_icc = isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size); + unsigned gray_png = info.color.colortype == LCT_GREY || info.color.colortype == LCT_GREY_ALPHA; + if(!gray_icc && !rgb_icc) { + state->error = 100; /* Disallowed profile color type for PNG */ + goto cleanup; + } + if(gray_icc != gray_png) { + /*Not allowed to use RGB/RGBA/palette with GRAY ICC profile or vice versa, + or in case of auto_convert, it wasn't possible to find appropriate model*/ + state->error = state->encoder.auto_convert ? 102 : 101; + goto cleanup; + } + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) { + unsigned char* converted; + size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7u) / 8u; + + converted = (unsigned char*)lodepng_malloc(size); + if(!converted && size) state->error = 83; /*alloc fail*/ + if(!state->error) { + state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h); + } + if(!state->error) { + state->error = preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder); + } + lodepng_free(converted); + if(state->error) goto cleanup; + } else { + state->error = preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder); + if(state->error) goto cleanup; + } + + /* output all PNG chunks */ { +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + size_t i; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*write signature and chunks*/ + state->error = writeSignature(&outv); + if(state->error) goto cleanup; + /*IHDR*/ + state->error = addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*unknown chunks between IHDR and PLTE*/ + if(info.unknown_chunks_data[0]) { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]); + if(state->error) goto cleanup; + } + /*color profile chunks must come before PLTE */ + if(info.iccp_defined) { + state->error = addChunk_iCCP(&outv, &info, &state->encoder.zlibsettings); + if(state->error) goto cleanup; + } + if(info.srgb_defined) { + state->error = addChunk_sRGB(&outv, &info); + if(state->error) goto cleanup; + } + if(info.gama_defined) { + state->error = addChunk_gAMA(&outv, &info); + if(state->error) goto cleanup; + } + if(info.chrm_defined) { + state->error = addChunk_cHRM(&outv, &info); + if(state->error) goto cleanup; + } + if(info_png->sbit_defined) { + state->error = addChunk_sBIT(&outv, &info); + if(state->error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*PLTE*/ + if(info.color.colortype == LCT_PALETTE) { + state->error = addChunk_PLTE(&outv, &info.color); + if(state->error) goto cleanup; + } + if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) { + /*force_palette means: write suggested palette for truecolor in PLTE chunk*/ + state->error = addChunk_PLTE(&outv, &info.color); + if(state->error) goto cleanup; + } + /*tRNS (this will only add if when necessary) */ + state->error = addChunk_tRNS(&outv, &info.color); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*bKGD (must come between PLTE and the IDAt chunks*/ + if(info.background_defined) { + state->error = addChunk_bKGD(&outv, &info); + if(state->error) goto cleanup; + } + /*pHYs (must come before the IDAT chunks)*/ + if(info.phys_defined) { + state->error = addChunk_pHYs(&outv, &info); + if(state->error) goto cleanup; + } + + /*unknown chunks between PLTE and IDAT*/ + if(info.unknown_chunks_data[1]) { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]); + if(state->error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*IDAT (multiple IDAT chunks must be consecutive)*/ + state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*tIME*/ + if(info.time_defined) { + state->error = addChunk_tIME(&outv, &info.time); + if(state->error) goto cleanup; + } + /*tEXt and/or zTXt*/ + for(i = 0; i != info.text_num; ++i) { + if(lodepng_strlen(info.text_keys[i]) > 79) { + state->error = 66; /*text chunk too large*/ + goto cleanup; + } + if(lodepng_strlen(info.text_keys[i]) < 1) { + state->error = 67; /*text chunk too small*/ + goto cleanup; + } + if(state->encoder.text_compression) { + state->error = addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings); + if(state->error) goto cleanup; + } else { + state->error = addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]); + if(state->error) goto cleanup; + } + } + /*LodePNG version id in text chunk*/ + if(state->encoder.add_id) { + unsigned already_added_id_text = 0; + for(i = 0; i != info.text_num; ++i) { + const char* k = info.text_keys[i]; + /* Could use strcmp, but we're not calling or reimplementing this C library function for this use only */ + if(k[0] == 'L' && k[1] == 'o' && k[2] == 'd' && k[3] == 'e' && + k[4] == 'P' && k[5] == 'N' && k[6] == 'G' && k[7] == '\0') { + already_added_id_text = 1; + break; + } + } + if(already_added_id_text == 0) { + state->error = addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/ + if(state->error) goto cleanup; + } + } + /*iTXt*/ + for(i = 0; i != info.itext_num; ++i) { + if(lodepng_strlen(info.itext_keys[i]) > 79) { + state->error = 66; /*text chunk too large*/ + goto cleanup; + } + if(lodepng_strlen(info.itext_keys[i]) < 1) { + state->error = 67; /*text chunk too small*/ + goto cleanup; + } + state->error = addChunk_iTXt( + &outv, state->encoder.text_compression, + info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i], + &state->encoder.zlibsettings); + if(state->error) goto cleanup; + } + + /*unknown chunks between IDAT and IEND*/ + if(info.unknown_chunks_data[2]) { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]); + if(state->error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + state->error = addChunk_IEND(&outv); + if(state->error) goto cleanup; + } + +cleanup: + lodepng_info_cleanup(&info); + lodepng_free(data); + lodepng_color_mode_cleanup(&auto_color); + + /*instead of cleaning the vector up, give it to the output*/ + *out = outv.data; + *outsize = outv.size; + + return state->error; +} + +unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image, + unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) { + unsigned error; + LodePNGState state; + lodepng_state_init(&state); + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + state.info_png.color.colortype = colortype; + state.info_png.color.bitdepth = bitdepth; + lodepng_encode(out, outsize, image, w, h, &state); + error = state.error; + lodepng_state_cleanup(&state); + return error; +} + +unsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) { + return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8); +} + +unsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) { + return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) { + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth); + if(!error) error = lodepng_save_file(buffer, buffersize, filename); + lodepng_free(buffer); + return error; +} + +unsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) { + return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8); +} + +unsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) { + return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8); +} +#endif /*LODEPNG_COMPILE_DISK*/ + +void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings) { + lodepng_compress_settings_init(&settings->zlibsettings); + settings->filter_palette_zero = 1; + settings->filter_strategy = LFS_MINSUM; + settings->auto_convert = 1; + settings->force_palette = 0; + settings->predefined_filters = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + settings->add_id = 0; + settings->text_compression = 1; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ERROR_TEXT +/* +This returns the description of a numerical error code in English. This is also +the documentation of all the error codes. +*/ +const char* lodepng_error_text(unsigned code) { + switch(code) { + case 0: return "no error, everything went ok"; + case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/ + case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/ + case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/ + case 13: return "problem while processing dynamic deflate block"; + case 14: return "problem while processing dynamic deflate block"; + case 15: return "problem while processing dynamic deflate block"; + /*this error could happen if there are only 0 or 1 symbols present in the huffman code:*/ + case 16: return "invalid code while processing dynamic deflate block"; + case 17: return "end of out buffer memory reached while inflating"; + case 18: return "invalid distance code while inflating"; + case 19: return "end of out buffer memory reached while inflating"; + case 20: return "invalid deflate block BTYPE encountered while decoding"; + case 21: return "NLEN is not ones complement of LEN in a deflate block"; + + /*end of out buffer memory reached while inflating: + This can happen if the inflated deflate data is longer than the amount of bytes required to fill up + all the pixels of the image, given the color depth and image dimensions. Something that doesn't + happen in a normal, well encoded, PNG image.*/ + case 22: return "end of out buffer memory reached while inflating"; + case 23: return "end of in buffer memory reached while inflating"; + case 24: return "invalid FCHECK in zlib header"; + case 25: return "invalid compression method in zlib header"; + case 26: return "FDICT encountered in zlib header while it's not used for PNG"; + case 27: return "PNG file is smaller than a PNG header"; + /*Checks the magic file header, the first 8 bytes of the PNG file*/ + case 28: return "incorrect PNG signature, it's no PNG or corrupted"; + case 29: return "first chunk is not the header chunk"; + case 30: return "chunk length too large, chunk broken off at end of file"; + case 31: return "illegal PNG color type or bpp"; + case 32: return "illegal PNG compression method"; + case 33: return "illegal PNG filter method"; + case 34: return "illegal PNG interlace method"; + case 35: return "chunk length of a chunk is too large or the chunk too small"; + case 36: return "illegal PNG filter type encountered"; + case 37: return "illegal bit depth for this color type given"; + case 38: return "the palette is too small or too big"; /*0, or more than 256 colors*/ + case 39: return "tRNS chunk before PLTE or has more entries than palette size"; + case 40: return "tRNS chunk has wrong size for grayscale image"; + case 41: return "tRNS chunk has wrong size for RGB image"; + case 42: return "tRNS chunk appeared while it was not allowed for this color type"; + case 43: return "bKGD chunk has wrong size for palette image"; + case 44: return "bKGD chunk has wrong size for grayscale image"; + case 45: return "bKGD chunk has wrong size for RGB image"; + case 48: return "empty input buffer given to decoder. Maybe caused by non-existing file?"; + case 49: return "jumped past memory while generating dynamic huffman tree"; + case 50: return "jumped past memory while generating dynamic huffman tree"; + case 51: return "jumped past memory while inflating huffman block"; + case 52: return "jumped past memory while inflating"; + case 53: return "size of zlib data too small"; + case 54: return "repeat symbol in tree while there was no value symbol yet"; + /*jumped past tree while generating huffman tree, this could be when the + tree will have more leaves than symbols after generating it out of the + given lengths. They call this an oversubscribed dynamic bit lengths tree in zlib.*/ + case 55: return "jumped past tree while generating huffman tree"; + case 56: return "given output image colortype or bitdepth not supported for color conversion"; + case 57: return "invalid CRC encountered (checking CRC can be disabled)"; + case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)"; + case 59: return "requested color conversion not supported"; + case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)"; + case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)"; + /*LodePNG leaves the choice of RGB to grayscale conversion formula to the user.*/ + case 62: return "conversion from color to grayscale not supported"; + /*(2^31-1)*/ + case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk"; + /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/ + case 64: return "the length of the END symbol 256 in the Huffman tree is 0"; + case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes"; + case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte"; + case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors"; + case 69: return "unknown chunk type with 'critical' flag encountered by the decoder"; + case 71: return "invalid interlace mode given to encoder (must be 0 or 1)"; + case 72: return "while decoding, invalid compression method encountering in zTXt or iTXt chunk (it must be 0)"; + case 73: return "invalid tIME chunk size"; + case 74: return "invalid pHYs chunk size"; + /*length could be wrong, or data chopped off*/ + case 75: return "no null termination char found while decoding text chunk"; + case 76: return "iTXt chunk too short to contain required bytes"; + case 77: return "integer overflow in buffer size"; + case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/ + case 79: return "failed to open file for writing"; + case 80: return "tried creating a tree of 0 symbols"; + case 81: return "lazy matching at pos 0 is impossible"; + case 82: return "color conversion to palette requested while a color isn't in palette, or index out of bounds"; + case 83: return "memory allocation failed"; + case 84: return "given image too small to contain all pixels to be encoded"; + case 86: return "impossible offset in lz77 encoding (internal bug)"; + case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined"; + case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy"; + case 89: return "text chunk keyword too short or long: must have size 1-79"; + /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/ + case 90: return "windowsize must be a power of two"; + case 91: return "invalid decompressed idat size"; + case 92: return "integer overflow due to too many pixels"; + case 93: return "zero width or height is invalid"; + case 94: return "header chunk must have a size of 13 bytes"; + case 95: return "integer overflow with combined idat chunk size"; + case 96: return "invalid gAMA chunk size"; + case 97: return "invalid cHRM chunk size"; + case 98: return "invalid sRGB chunk size"; + case 99: return "invalid sRGB rendering intent"; + case 100: return "invalid ICC profile color type, the PNG specification only allows RGB or GRAY"; + case 101: return "PNG specification does not allow RGB ICC profile on gray color types and vice versa"; + case 102: return "not allowed to set grayscale ICC profile with colored pixels by PNG specification"; + case 103: return "invalid palette index in bKGD chunk. Maybe it came before PLTE chunk?"; + case 104: return "invalid bKGD color while encoding (e.g. palette index out of range)"; + case 105: return "integer overflow of bitsize"; + case 106: return "PNG file must have PLTE chunk if color type is palette"; + case 107: return "color convert from palette mode requested without setting the palette data in it"; + case 108: return "tried to add more than 256 values to a palette"; + /*this limit can be configured in LodePNGDecompressSettings*/ + case 109: return "tried to decompress zlib or deflate data larger than desired max_output_size"; + case 110: return "custom zlib or inflate decompression failed"; + case 111: return "custom zlib or deflate compression failed"; + /*max text size limit can be configured in LodePNGDecoderSettings. This error prevents + unreasonable memory consumption when decoding due to impossibly large text sizes.*/ + case 112: return "compressed text unreasonably large"; + /*max ICC size limit can be configured in LodePNGDecoderSettings. This error prevents + unreasonable memory consumption when decoding due to impossibly large ICC profile*/ + case 113: return "ICC profile unreasonably large"; + case 114: return "sBIT chunk has wrong size for the color type of the image"; + case 115: return "sBIT value out of range"; + } + return "unknown error code"; +} +#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // C++ Wrapper // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_CPP +namespace lodepng { + +#ifdef LODEPNG_COMPILE_DISK +unsigned load_file(std::vector& buffer, const std::string& filename) { + long size = lodepng_filesize(filename.c_str()); + if(size < 0) return 78; + buffer.resize((size_t)size); + return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str()); +} + +/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ +unsigned save_file(const std::vector& buffer, const std::string& filename) { + return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str()); +} +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_DECODER +unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings& settings) { + unsigned char* buffer = 0; + size_t buffersize = 0; + unsigned error = zlib_decompress(&buffer, &buffersize, 0, in, insize, &settings); + if(buffer) { + out.insert(out.end(), buffer, &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned decompress(std::vector& out, const std::vector& in, + const LodePNGDecompressSettings& settings) { + return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings); +} +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +unsigned compress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings& settings) { + unsigned char* buffer = 0; + size_t buffersize = 0; + unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings); + if(buffer) { + out.insert(out.end(), buffer, &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned compress(std::vector& out, const std::vector& in, + const LodePNGCompressSettings& settings) { + return compress(out, in.empty() ? 0 : &in[0], in.size(), settings); +} +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_ZLIB */ + + +#ifdef LODEPNG_COMPILE_PNG + +State::State() { + lodepng_state_init(this); +} + +State::State(const State& other) { + lodepng_state_init(this); + lodepng_state_copy(this, &other); +} + +State::~State() { + lodepng_state_cleanup(this); +} + +State& State::operator=(const State& other) { + lodepng_state_copy(this, &other); + return *this; +} + +#ifdef LODEPNG_COMPILE_DECODER + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, const unsigned char* in, + size_t insize, LodePNGColorType colortype, unsigned bitdepth) { + unsigned char* buffer = 0; + unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth); + if(buffer && !error) { + State state; + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); + out.insert(out.end(), buffer, &buffer[buffersize]); + } + lodepng_free(buffer); + return error; +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::vector& in, LodePNGColorType colortype, unsigned bitdepth) { + return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth); +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const unsigned char* in, size_t insize) { + unsigned char* buffer = NULL; + unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize); + if(buffer && !error) { + size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); + out.insert(out.end(), buffer, &buffer[buffersize]); + } + lodepng_free(buffer); + return error; +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const std::vector& in) { + return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size()); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::string& filename, + LodePNGColorType colortype, unsigned bitdepth) { + std::vector buffer; + /* safe output values in case error happens */ + w = h = 0; + unsigned error = load_file(buffer, filename); + if(error) return error; + return decode(out, w, h, buffer, colortype, bitdepth); +} +#endif /* LODEPNG_COMPILE_DECODER */ +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ENCODER +unsigned encode(std::vector& out, const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) { + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth); + if(buffer) { + out.insert(out.end(), buffer, &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) { + if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; + return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); +} + +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + State& state) { + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state); + if(buffer) { + out.insert(out.end(), buffer, &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + State& state) { + if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84; + return encode(out, in.empty() ? 0 : &in[0], w, h, state); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned encode(const std::string& filename, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) { + std::vector buffer; + unsigned error = encode(buffer, in, w, h, colortype, bitdepth); + if(!error) error = save_file(buffer, filename); + return error; +} + +unsigned encode(const std::string& filename, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) { + if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; + return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); +} +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_PNG */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/resources/lodepng.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/resources/lodepng.h Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,2089 @@ +/* +LodePNG version 20230410 + +Copyright (c) 2005-2023 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +#ifndef LODEPNG_H +#define LODEPNG_H + +#include /*for size_t*/ + +extern const char* LODEPNG_VERSION_STRING; + +/* +The following #defines are used to create code sections. They can be disabled +to disable code sections, which can give faster compile time and smaller binary. +The "NO_COMPILE" defines are designed to be used to pass as defines to the +compiler command to disable them without modifying this header, e.g. +-DLODEPNG_NO_COMPILE_ZLIB for gcc or clang. +*/ +/*deflate & zlib. If disabled, you must specify alternative zlib functions in +the custom_zlib field of the compress and decompress settings*/ +#ifndef LODEPNG_NO_COMPILE_ZLIB +/*pass -DLODEPNG_NO_COMPILE_ZLIB to the compiler to disable this, or comment out LODEPNG_COMPILE_ZLIB below*/ +#define LODEPNG_COMPILE_ZLIB +#endif + +/*png encoder and png decoder*/ +#ifndef LODEPNG_NO_COMPILE_PNG +/*pass -DLODEPNG_NO_COMPILE_PNG to the compiler to disable this, or comment out LODEPNG_COMPILE_PNG below*/ +#define LODEPNG_COMPILE_PNG +#endif + +/*deflate&zlib decoder and png decoder*/ +#ifndef LODEPNG_NO_COMPILE_DECODER +/*pass -DLODEPNG_NO_COMPILE_DECODER to the compiler to disable this, or comment out LODEPNG_COMPILE_DECODER below*/ +#define LODEPNG_COMPILE_DECODER +#endif + +/*deflate&zlib encoder and png encoder*/ +#ifndef LODEPNG_NO_COMPILE_ENCODER +/*pass -DLODEPNG_NO_COMPILE_ENCODER to the compiler to disable this, or comment out LODEPNG_COMPILE_ENCODER below*/ +#define LODEPNG_COMPILE_ENCODER +#endif + +/*the optional built in harddisk file loading and saving functions*/ +#ifndef LODEPNG_NO_COMPILE_DISK +/*pass -DLODEPNG_NO_COMPILE_DISK to the compiler to disable this, or comment out LODEPNG_COMPILE_DISK below*/ +#define LODEPNG_COMPILE_DISK +#endif + +/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/ +#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS +/*pass -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS to the compiler to disable this, +or comment out LODEPNG_COMPILE_ANCILLARY_CHUNKS below*/ +#define LODEPNG_COMPILE_ANCILLARY_CHUNKS +#endif + +/*ability to convert error numerical codes to English text string*/ +#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT +/*pass -DLODEPNG_NO_COMPILE_ERROR_TEXT to the compiler to disable this, +or comment out LODEPNG_COMPILE_ERROR_TEXT below*/ +#define LODEPNG_COMPILE_ERROR_TEXT +#endif + +/*Compile the default allocators (C's free, malloc and realloc). If you disable this, +you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your +source files with custom allocators.*/ +#ifndef LODEPNG_NO_COMPILE_ALLOCATORS +/*pass -DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler to disable the built-in ones, +or comment out LODEPNG_COMPILE_ALLOCATORS below*/ +#define LODEPNG_COMPILE_ALLOCATORS +#endif + +/*Disable built-in CRC function, in that case a custom implementation of +lodepng_crc32 must be defined externally so that it can be linked in. +The default built-in CRC code comes with 8KB of lookup tables, so for memory constrained environment you may want it +disabled and provide a much smaller implementation externally as said above. You can find such an example implementation +in a comment in the lodepng.c(pp) file in the 'else' case of the searchable LODEPNG_COMPILE_CRC section.*/ +#ifndef LODEPNG_NO_COMPILE_CRC +/*pass -DLODEPNG_NO_COMPILE_CRC to the compiler to disable the built-in one, +or comment out LODEPNG_COMPILE_CRC below*/ +#define LODEPNG_COMPILE_CRC +#endif + +/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/ +#ifdef __cplusplus +#ifndef LODEPNG_NO_COMPILE_CPP +/*pass -DLODEPNG_NO_COMPILE_CPP to the compiler to disable C++ (not needed if a C-only compiler), +or comment out LODEPNG_COMPILE_CPP below*/ +#define LODEPNG_COMPILE_CPP +#endif +#endif + +#ifdef LODEPNG_COMPILE_CPP +#include +#include +#endif /*LODEPNG_COMPILE_CPP*/ + +#ifdef LODEPNG_COMPILE_PNG +/*The PNG color types (also used for raw image).*/ +typedef enum LodePNGColorType { + LCT_GREY = 0, /*grayscale: 1,2,4,8,16 bit*/ + LCT_RGB = 2, /*RGB: 8,16 bit*/ + LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/ + LCT_GREY_ALPHA = 4, /*grayscale with alpha: 8,16 bit*/ + LCT_RGBA = 6, /*RGB with alpha: 8,16 bit*/ + /*LCT_MAX_OCTET_VALUE lets the compiler allow this enum to represent any invalid + byte value from 0 to 255 that could be present in an invalid PNG file header. Do + not use, compare with or set the name LCT_MAX_OCTET_VALUE, instead either use + the valid color type names above, or numeric values like 1 or 7 when checking for + particular disallowed color type byte values, or cast to integer to print it.*/ + LCT_MAX_OCTET_VALUE = 255 +} LodePNGColorType; + +#ifdef LODEPNG_COMPILE_DECODER +/* +Converts PNG data in memory to raw pixel data. +out: Output parameter. Pointer to buffer that will contain the raw pixel data. + After decoding, its size is w * h * (bytes per pixel) bytes larger than + initially. Bytes per pixel depends on colortype and bitdepth. + Must be freed after usage with free(*out). + Note: for 16-bit per channel colors, uses big endian format like PNG does. +w: Output parameter. Pointer to width of pixel data. +h: Output parameter. Pointer to height of pixel data. +in: Memory buffer with the PNG file. +insize: size of the in buffer. +colortype: the desired color type for the raw output image. See explanation on PNG color types. +bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types. +Return value: LodePNG error code (0 means no error). +*/ +unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/ +unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize); + +/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/ +unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize); + +#ifdef LODEPNG_COMPILE_DISK +/* +Load PNG from disk, from file with given name. +Same as the other decode functions, but instead takes a filename as input. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory.*/ +unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory.*/ +unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename); + +/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory.*/ +unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename); +#endif /*LODEPNG_COMPILE_DISK*/ +#endif /*LODEPNG_COMPILE_DECODER*/ + + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Converts raw pixel data into a PNG image in memory. The colortype and bitdepth + of the output PNG image cannot be chosen, they are automatically determined + by the colortype, bitdepth and content of the input pixel data. + Note: for 16-bit per channel colors, needs big endian format like PNG does. +out: Output parameter. Pointer to buffer that will contain the PNG image data. + Must be freed after usage with free(*out). +outsize: Output parameter. Pointer to the size in bytes of the out buffer. +image: The raw pixel data to encode. The size of this buffer should be + w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth. +w: width of the raw pixel data in pixels. +h: height of the raw pixel data in pixels. +colortype: the color type of the raw input image. See explanation on PNG color types. +bitdepth: the bit depth of the raw input image. See explanation on PNG color types. +Return value: LodePNG error code (0 means no error). +*/ +unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/ +unsigned lodepng_encode32(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h); + +/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/ +unsigned lodepng_encode24(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h); + +#ifdef LODEPNG_COMPILE_DISK +/* +Converts raw pixel data into a PNG file on disk. +Same as the other encode functions, but instead takes a filename as output. + +NOTE: This overwrites existing files without warning! + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and encode in-memory.*/ +unsigned lodepng_encode_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and encode in-memory.*/ +unsigned lodepng_encode32_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h); + +/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and encode in-memory.*/ +unsigned lodepng_encode24_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h); +#endif /*LODEPNG_COMPILE_DISK*/ +#endif /*LODEPNG_COMPILE_ENCODER*/ + + +#ifdef LODEPNG_COMPILE_CPP +namespace lodepng { +#ifdef LODEPNG_COMPILE_DECODER +/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype +is the format to output the pixels to. Default is RGBA 8-bit per channel.*/ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const unsigned char* in, size_t insize, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::vector& in, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#ifdef LODEPNG_COMPILE_DISK +/* +Converts PNG file from disk to raw pixel data in memory. +Same as the other decode functions, but instead takes a filename as input. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory. +*/ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::string& filename, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype +is that of the raw input data. The output PNG color type will be auto chosen.*/ +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#ifdef LODEPNG_COMPILE_DISK +/* +Converts 32-bit RGBA raw pixel data into a PNG file on disk. +Same as the other encode functions, but instead takes a filename as output. + +NOTE: This overwrites existing files without warning! + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory. +*/ +unsigned encode(const std::string& filename, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned encode(const std::string& filename, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_ENCODER */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ERROR_TEXT +/*Returns an English description of the numerical error code.*/ +const char* lodepng_error_text(unsigned code); +#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ + +#ifdef LODEPNG_COMPILE_DECODER +/*Settings for zlib decompression*/ +typedef struct LodePNGDecompressSettings LodePNGDecompressSettings; +struct LodePNGDecompressSettings { + /* Check LodePNGDecoderSettings for more ignorable errors such as ignore_crc */ + unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ + unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/ + + /*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding, + return an error, output a data size > max_output_size and all the data up to that point. This is + not hard limit nor a guarantee, but can prevent excessive memory usage. This setting is + ignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones. + Set to 0 to impose no limit (the default).*/ + size_t max_output_size; + + /*use custom zlib decoder instead of built in one (default: null). + Should return 0 if success, any non-0 if error (numeric value not exposed).*/ + unsigned (*custom_zlib)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGDecompressSettings*); + /*use custom deflate decoder instead of built in one (default: null) + if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate). + Should return 0 if success, any non-0 if error (numeric value not exposed).*/ + unsigned (*custom_inflate)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGDecompressSettings*); + + const void* custom_context; /*optional custom settings for custom functions*/ +}; + +extern const LodePNGDecompressSettings lodepng_default_decompress_settings; +void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Settings for zlib compression. Tweaking these settings tweaks the balance +between speed and compression ratio. +*/ +typedef struct LodePNGCompressSettings LodePNGCompressSettings; +struct LodePNGCompressSettings /*deflate = compress*/ { + /*LZ77 related settings*/ + unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/ + unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/ + unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/ + unsigned minmatch; /*minimum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/ + unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/ + unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/ + + /*use custom zlib encoder instead of built in one (default: null)*/ + unsigned (*custom_zlib)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGCompressSettings*); + /*use custom deflate encoder instead of built in one (default: null) + if custom_zlib is used, custom_deflate is ignored since only the built in + zlib function will call custom_deflate*/ + unsigned (*custom_deflate)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGCompressSettings*); + + const void* custom_context; /*optional custom settings for custom functions*/ +}; + +extern const LodePNGCompressSettings lodepng_default_compress_settings; +void lodepng_compress_settings_init(LodePNGCompressSettings* settings); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_PNG +/* +Color mode of an image. Contains all information required to decode the pixel +bits to RGBA colors. This information is the same as used in the PNG file +format, and is used both for PNG and raw image data in LodePNG. +*/ +typedef struct LodePNGColorMode { + /*header (IHDR)*/ + LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/ + unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/ + + /* + palette (PLTE and tRNS) + + Dynamically allocated with the colors of the palette, including alpha. + This field may not be allocated directly, use lodepng_color_mode_init first, + then lodepng_palette_add per color to correctly initialize it (to ensure size + of exactly 1024 bytes). + + The alpha channels must be set as well, set them to 255 for opaque images. + + When decoding, with the default settings you can ignore this palette, since + LodePNG already fills the palette colors in the pixels of the raw RGBA output, + but when decoding to the original PNG color mode it is needed to reconstruct + the colors. + + The palette is only supported for color type 3. + */ + unsigned char* palette; /*palette in RGBARGBA... order. Must be either 0, or when allocated must have 1024 bytes*/ + size_t palettesize; /*palette size in number of colors (amount of used bytes is 4 * palettesize)*/ + + /* + transparent color key (tRNS) + + This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit. + For grayscale PNGs, r, g and b will all 3 be set to the same. + + When decoding, by default you can ignore this information, since LodePNG sets + pixels with this key to transparent already in the raw RGBA output. + + The color key is only supported for color types 0 and 2. + */ + unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/ + unsigned key_r; /*red/grayscale component of color key*/ + unsigned key_g; /*green component of color key*/ + unsigned key_b; /*blue component of color key*/ +} LodePNGColorMode; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_color_mode_init(LodePNGColorMode* info); +void lodepng_color_mode_cleanup(LodePNGColorMode* info); +/*return value is error code (0 means no error)*/ +unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source); +/* Makes a temporary LodePNGColorMode that does not need cleanup (no palette) */ +LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth); + +void lodepng_palette_clear(LodePNGColorMode* info); +/*add 1 color to the palette*/ +unsigned lodepng_palette_add(LodePNGColorMode* info, + unsigned char r, unsigned char g, unsigned char b, unsigned char a); + +/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/ +unsigned lodepng_get_bpp(const LodePNGColorMode* info); +/*get the amount of color channels used, based on colortype in the struct. +If a palette is used, it counts as 1 channel.*/ +unsigned lodepng_get_channels(const LodePNGColorMode* info); +/*is it a grayscale type? (only colortype 0 or 4)*/ +unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info); +/*has it got an alpha channel? (only colortype 2 or 6)*/ +unsigned lodepng_is_alpha_type(const LodePNGColorMode* info); +/*has it got a palette? (only colortype 3)*/ +unsigned lodepng_is_palette_type(const LodePNGColorMode* info); +/*only returns true if there is a palette and there is a value in the palette with alpha < 255. +Loops through the palette to check this.*/ +unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info); +/* +Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image. +Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels). +Returns false if the image can only have opaque pixels. +In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values, +or if "key_defined" is true. +*/ +unsigned lodepng_can_have_alpha(const LodePNGColorMode* info); +/*Returns the byte size of a raw image buffer with given width, height and color mode*/ +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*The information of a Time chunk in PNG.*/ +typedef struct LodePNGTime { + unsigned year; /*2 bytes used (0-65535)*/ + unsigned month; /*1-12*/ + unsigned day; /*1-31*/ + unsigned hour; /*0-23*/ + unsigned minute; /*0-59*/ + unsigned second; /*0-60 (to allow for leap seconds)*/ +} LodePNGTime; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/*Information about the PNG image, except pixels, width and height.*/ +typedef struct LodePNGInfo { + /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/ + unsigned compression_method;/*compression method of the original file. Always 0.*/ + unsigned filter_method; /*filter method of the original file*/ + unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/ + LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /* + Suggested background color chunk (bKGD) + + This uses the same color mode and bit depth as the PNG (except no alpha channel), + with values truncated to the bit depth in the unsigned integer. + + For grayscale and palette PNGs, the value is stored in background_r. The values + in background_g and background_b are then unused. The decoder will set them + equal to background_r, the encoder ignores them in this case. + + When decoding, you may get these in a different color mode than the one you requested + for the raw pixels: the colortype and bitdepth defined by info_png.color, that is the + ones defined in the header of the PNG image, are used. + + When encoding with auto_convert, you must use the color model defined in info_png.color for + these values. The encoder normally ignores info_png.color when auto_convert is on, but will + use it to interpret these values (and convert copies of them to its chosen color model). + + When encoding, avoid setting this to an expensive color, such as a non-gray value + when the image is gray, or the compression will be worse since it will be forced to + write the PNG with a more expensive color mode (when auto_convert is on). + + The decoder does not use this background color to edit the color of pixels. This is a + completely optional metadata feature. + */ + unsigned background_defined; /*is a suggested background color given?*/ + unsigned background_r; /*red/gray/palette component of suggested background color*/ + unsigned background_g; /*green component of suggested background color*/ + unsigned background_b; /*blue component of suggested background color*/ + + /* + Non-international text chunks (tEXt and zTXt) + + The char** arrays each contain num strings. The actual messages are in + text_strings, while text_keys are keywords that give a short description what + the actual text represents, e.g. Title, Author, Description, or anything else. + + All the string fields below including strings, keys, names and language tags are null terminated. + The PNG specification uses null characters for the keys, names and tags, and forbids null + characters to appear in the main text which is why we can use null termination everywhere here. + + A keyword is minimum 1 character and maximum 79 characters long (plus the + additional null terminator). It's discouraged to use a single line length + longer than 79 characters for texts. + + Don't allocate these text buffers yourself. Use the init/cleanup functions + correctly and use lodepng_add_text and lodepng_clear_text. + + Standard text chunk keywords and strings are encoded using Latin-1. + */ + size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/ + char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/ + char** text_strings; /*the actual text*/ + + /* + International text chunks (iTXt) + Similar to the non-international text chunks, but with additional strings + "langtags" and "transkeys", and the following text encodings are used: + keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8. + keys must be 1-79 characters (plus the additional null terminator), the other + strings are any length. + */ + size_t itext_num; /*the amount of international texts in this PNG*/ + char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/ + char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/ + char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/ + char** itext_strings; /*the actual international text - UTF-8 string*/ + + /*time chunk (tIME)*/ + unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/ + LodePNGTime time; + + /*phys chunk (pHYs)*/ + unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/ + unsigned phys_x; /*pixels per unit in x direction*/ + unsigned phys_y; /*pixels per unit in y direction*/ + unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/ + + /* + Color profile related chunks: gAMA, cHRM, sRGB, iCPP, sBIT + + LodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these color + profile values. It merely passes on the information. If you wish to use color profiles and convert colors, please + use these values with a color management library. + + See the PNG, ICC and sRGB specifications for more information about the meaning of these values. + */ + + /* gAMA chunk: optional, overridden by sRGB or iCCP if those are present. */ + unsigned gama_defined; /* Whether a gAMA chunk is present (0 = not present, 1 = present). */ + unsigned gama_gamma; /* Gamma exponent times 100000 */ + + /* cHRM chunk: optional, overridden by sRGB or iCCP if those are present. */ + unsigned chrm_defined; /* Whether a cHRM chunk is present (0 = not present, 1 = present). */ + unsigned chrm_white_x; /* White Point x times 100000 */ + unsigned chrm_white_y; /* White Point y times 100000 */ + unsigned chrm_red_x; /* Red x times 100000 */ + unsigned chrm_red_y; /* Red y times 100000 */ + unsigned chrm_green_x; /* Green x times 100000 */ + unsigned chrm_green_y; /* Green y times 100000 */ + unsigned chrm_blue_x; /* Blue x times 100000 */ + unsigned chrm_blue_y; /* Blue y times 100000 */ + + /* + sRGB chunk: optional. May not appear at the same time as iCCP. + If gAMA is also present gAMA must contain value 45455. + If cHRM is also present cHRM must contain respectively 31270,32900,64000,33000,30000,60000,15000,6000. + */ + unsigned srgb_defined; /* Whether an sRGB chunk is present (0 = not present, 1 = present). */ + unsigned srgb_intent; /* Rendering intent: 0=perceptual, 1=rel. colorimetric, 2=saturation, 3=abs. colorimetric */ + + /* + iCCP chunk: optional. May not appear at the same time as sRGB. + + LodePNG does not parse or use the ICC profile (except its color space header field for an edge case), a + separate library to handle the ICC data (not included in LodePNG) format is needed to use it for color + management and conversions. + + For encoding, if iCCP is present, gAMA and cHRM are recommended to be added as well with values that match the ICC + profile as closely as possible, if you wish to do this you should provide the correct values for gAMA and cHRM and + enable their '_defined' flags since LodePNG will not automatically compute them from the ICC profile. + + For encoding, the ICC profile is required by the PNG specification to be an "RGB" profile for non-gray + PNG color types and a "GRAY" profile for gray PNG color types. If you disable auto_convert, you must ensure + the ICC profile type matches your requested color type, else the encoder gives an error. If auto_convert is + enabled (the default), and the ICC profile is not a good match for the pixel data, this will result in an encoder + error if the pixel data has non-gray pixels for a GRAY profile, or a silent less-optimal compression of the pixel + data if the pixels could be encoded as grayscale but the ICC profile is RGB. + + To avoid this do not set an ICC profile in the image unless there is a good reason for it, and when doing so + make sure you compute it carefully to avoid the above problems. + */ + unsigned iccp_defined; /* Whether an iCCP chunk is present (0 = not present, 1 = present). */ + char* iccp_name; /* Null terminated string with profile name, 1-79 bytes */ + /* + The ICC profile in iccp_profile_size bytes. + Don't allocate this buffer yourself. Use the init/cleanup functions + correctly and use lodepng_set_icc and lodepng_clear_icc. + */ + unsigned char* iccp_profile; + unsigned iccp_profile_size; /* The size of iccp_profile in bytes */ + + /* + sBIT chunk: significant bits. Optional metadata, only set this if needed. + + If defined, these values give the bit depth of the original data. Since PNG only stores 1, 2, 4, 8 or 16-bit + per channel data, the significant bits value can be used to indicate the original encoded data has another + sample depth, such as 10 or 12. + + Encoders using this value, when storing the pixel data, should use the most significant bits + of the data to store the original bits, and use a good sample depth scaling method such as + "left bit replication" to fill in the least significant bits, rather than fill zeroes. + + Decoders using this value, if able to work with data that's e.g. 10-bit or 12-bit, should right + shift the data to go back to the original bit depth, but decoders are also allowed to ignore + sbit and work e.g. with the 8-bit or 16-bit data from the PNG directly, since thanks + to the encoder contract, the values encoded in PNG are in valid range for the PNG bit depth. + + For grayscale images, sbit_g and sbit_b are not used, and for images that don't use color + type RGBA or grayscale+alpha, sbit_a is not used (it's not used even for palette images with + translucent palette values, or images with color key). The values that are used must be + greater than zero and smaller than or equal to the PNG bit depth. + + The color type from the header in the PNG image defines these used and unused fields: if + decoding with a color mode conversion, such as always decoding to RGBA, this metadata still + only uses the color type of the original PNG, and may e.g. lack the alpha channel info + if the PNG was RGB. When encoding with auto_convert (as well as without), also always the + color model defined in info_png.color determines this. + + NOTE: enabling sbit can hurt compression, because the encoder can then not always use + auto_convert to choose a more optimal color mode for the data, because the PNG format has + strict requirements for the allowed sbit values in combination with color modes. + For example, setting these fields to 10-bit will force the encoder to keep using a 16-bit per channel + color mode, even if the pixel data would in fact fit in a more efficient 8-bit mode. + */ + unsigned sbit_defined; /*is significant bits given? if not, the values below are unused*/ + unsigned sbit_r; /*red or gray component of significant bits*/ + unsigned sbit_g; /*green component of significant bits*/ + unsigned sbit_b; /*blue component of significant bits*/ + unsigned sbit_a; /*alpha component of significant bits*/ + + /* End of color profile related chunks */ + + + /* + unknown chunks: chunks not known by LodePNG, passed on byte for byte. + + There are 3 buffers, one for each position in the PNG where unknown chunks can appear. + Each buffer contains all unknown chunks for that position consecutively. + The 3 positions are: + 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND. + + For encoding, do not store critical chunks or known chunks that are enabled with a "_defined" flag + above in here, since the encoder will blindly follow this and could then encode an invalid PNG file + (such as one with two IHDR chunks or the disallowed combination of sRGB with iCCP). But do use + this if you wish to store an ancillary chunk that is not supported by LodePNG (such as sPLT or hIST), + or any non-standard PNG chunk. + + Do not allocate or traverse this data yourself. Use the chunk traversing functions declared + later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct. + */ + unsigned char* unknown_chunks_data[3]; + size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGInfo; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_info_init(LodePNGInfo* info); +void lodepng_info_cleanup(LodePNGInfo* info); +/*return value is error code (0 means no error)*/ +unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/ +void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ + +unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/ +void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/ + +/*replaces if exists*/ +unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size); +void lodepng_clear_icc(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/* +Converts raw buffer from one color type to another color type, based on +LodePNGColorMode structs to describe the input and output color type. +See the reference manual at the end of this header file to see which color conversions are supported. +return value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported) +The out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel +of the output color type (lodepng_get_bpp). +For < 8 bpp images, there should not be padding bits at the end of scanlines. +For 16-bit per channel colors, uses big endian format like PNG does. +Return value is LodePNG error code +*/ +unsigned lodepng_convert(unsigned char* out, const unsigned char* in, + const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, + unsigned w, unsigned h); + +#ifdef LODEPNG_COMPILE_DECODER +/* +Settings for the decoder. This contains settings for the PNG and the Zlib +decoder, but not the Info settings from the Info structs. +*/ +typedef struct LodePNGDecoderSettings { + LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ + + /* Check LodePNGDecompressSettings for more ignorable errors such as ignore_adler32 */ + unsigned ignore_crc; /*ignore CRC checksums*/ + unsigned ignore_critical; /*ignore unknown critical chunks*/ + unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/ + /* TODO: make a system involving warnings with levels and a strict mode instead. Other potentially recoverable + errors: srgb rendering intent value, size of content of ancillary chunks, more than 79 characters for some + strings, placement/combination rules for ancillary chunks, crc of unknown chunks, allowed characters + in string keys, etc... */ + + unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/ + + /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/ + unsigned remember_unknown_chunks; + + /* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned, + unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size. + By default it is a value that prevents unreasonably large strings from hogging memory. */ + size_t max_text_size; + + /* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to + 0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than any + legitimate profile could be to hog memory. */ + size_t max_icc_size; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGDecoderSettings; + +void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/ +typedef enum LodePNGFilterStrategy { + /*every filter at zero*/ + LFS_ZERO = 0, + /*every filter at 1, 2, 3 or 4 (paeth), unlike LFS_ZERO not a good choice, but for testing*/ + LFS_ONE = 1, + LFS_TWO = 2, + LFS_THREE = 3, + LFS_FOUR = 4, + /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/ + LFS_MINSUM, + /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending + on the image, this is better or worse than minsum.*/ + LFS_ENTROPY, + /* + Brute-force-search PNG filters by compressing each filter for each scanline. + Experimental, very slow, and only rarely gives better compression than MINSUM. + */ + LFS_BRUTE_FORCE, + /*use predefined_filters buffer: you specify the filter type for each scanline*/ + LFS_PREDEFINED +} LodePNGFilterStrategy; + +/*Gives characteristics about the integer RGBA colors of the image (count, alpha channel usage, bit depth, ...), +which helps decide which color model to use for encoding. +Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms.*/ +typedef struct LodePNGColorStats { + unsigned colored; /*not grayscale*/ + unsigned key; /*image is not opaque and color key is possible instead of full alpha*/ + unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/ + unsigned short key_g; + unsigned short key_b; + unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/ + unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16 or allow_palette is disabled.*/ + unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order, only valid when numcolors is valid*/ + unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for grayscale only. 16 if 16-bit per channel required.*/ + size_t numpixels; + + /*user settings for computing/using the stats*/ + unsigned allow_palette; /*default 1. if 0, disallow choosing palette colortype in auto_choose_color, and don't count numcolors*/ + unsigned allow_greyscale; /*default 1. if 0, choose RGB or RGBA even if the image only has gray colors*/ +} LodePNGColorStats; + +void lodepng_color_stats_init(LodePNGColorStats* stats); + +/*Get a LodePNGColorStats of the image. The stats must already have been inited. +Returns error code (e.g. alloc fail) or 0 if ok.*/ +unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, + const unsigned char* image, unsigned w, unsigned h, + const LodePNGColorMode* mode_in); + +/*Settings for the encoder.*/ +typedef struct LodePNGEncoderSettings { + LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ + + unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/ + + /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than + 8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to + completely follow the official PNG heuristic, filter_palette_zero must be true and + filter_strategy must be LFS_MINSUM*/ + unsigned filter_palette_zero; + /*Which filter strategy to use when not using zeroes due to filter_palette_zero. + Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/ + LodePNGFilterStrategy filter_strategy; + /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with + the same length as the amount of scanlines in the image, and each value must <= 5. You + have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero + must be set to 0 to ensure this is also used on palette or low bitdepth images.*/ + const unsigned char* predefined_filters; + + /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). + If colortype is 3, PLTE is always created. If color type is explicitely set + to a grayscale type (1 or 4), this is not done and is ignored. If enabling this, + a palette must be present in the info_png. + NOTE: enabling this may worsen compression if auto_convert is used to choose + optimal color mode, because it cannot use grayscale color modes in this case*/ + unsigned force_palette; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*add LodePNG identifier and version as a text chunk, for debugging*/ + unsigned add_id; + /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/ + unsigned text_compression; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGEncoderSettings; + +void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings); +#endif /*LODEPNG_COMPILE_ENCODER*/ + + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) +/*The settings, state and information for extended encoding and decoding.*/ +typedef struct LodePNGState { +#ifdef LODEPNG_COMPILE_DECODER + LodePNGDecoderSettings decoder; /*the decoding settings*/ +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER + LodePNGEncoderSettings encoder; /*the encoding settings*/ +#endif /*LODEPNG_COMPILE_ENCODER*/ + LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/ + LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/ + unsigned error; +} LodePNGState; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_state_init(LodePNGState* state); +void lodepng_state_cleanup(LodePNGState* state); +void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source); +#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ + +#ifdef LODEPNG_COMPILE_DECODER +/* +Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and +getting much more information about the PNG image and color mode. +*/ +unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize); + +/* +Read the PNG header, but not the actual data. This returns only the information +that is in the IHDR chunk of the PNG, such as width, height and color type. The +information is placed in the info_png field of the LodePNGState. +*/ +unsigned lodepng_inspect(unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize); +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* +Reads one metadata chunk (other than IHDR, which is handled by lodepng_inspect) +of the PNG file and outputs what it read in the state. Returns error code on failure. +Use lodepng_inspect first with a new state, then e.g. lodepng_chunk_find_const +to find the desired chunk type, and if non null use lodepng_inspect_chunk (with +chunk_pointer - start_of_file as pos). +Supports most metadata chunks from the PNG standard (gAMA, bKGD, tEXt, ...). +Ignores unsupported, unknown, non-metadata or IHDR chunks (without error). +Requirements: &in[pos] must point to start of a chunk, must use regular +lodepng_inspect first since format of most other chunks depends on IHDR, and if +there is a PLTE chunk, that one must be inspected before tRNS or bKGD. +*/ +unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, + const unsigned char* in, size_t insize); + +#ifdef LODEPNG_COMPILE_ENCODER +/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/ +unsigned lodepng_encode(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGState* state); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/* +The lodepng_chunk functions are normally not needed, except to traverse the +unknown chunks stored in the LodePNGInfo struct, or add new ones to it. +It also allows traversing the chunks of an encoded PNG file yourself. + +The chunk pointer always points to the beginning of the chunk itself, that is +the first byte of the 4 length bytes. + +In the PNG file format, chunks have the following format: +-4 bytes length: length of the data of the chunk in bytes (chunk itself is 12 bytes longer) +-4 bytes chunk type (ASCII a-z,A-Z only, see below) +-length bytes of data (may be 0 bytes if length was 0) +-4 bytes of CRC, computed on chunk name + data + +The first chunk starts at the 8th byte of the PNG file, the entire rest of the file +exists out of concatenated chunks with the above format. + +PNG standard chunk ASCII naming conventions: +-First byte: uppercase = critical, lowercase = ancillary +-Second byte: uppercase = public, lowercase = private +-Third byte: must be uppercase +-Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy +*/ + +/* +Gets the length of the data of the chunk. Total chunk length has 12 bytes more. +There must be at least 4 bytes to read from. If the result value is too large, +it may be corrupt data. +*/ +unsigned lodepng_chunk_length(const unsigned char* chunk); + +/*puts the 4-byte type in null terminated string*/ +void lodepng_chunk_type(char type[5], const unsigned char* chunk); + +/*check if the type is the given type*/ +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type); + +/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/ +unsigned char lodepng_chunk_ancillary(const unsigned char* chunk); + +/*0: public, 1: private (see PNG standard)*/ +unsigned char lodepng_chunk_private(const unsigned char* chunk); + +/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/ +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk); + +/*get pointer to the data of the chunk, where the input points to the header of the chunk*/ +unsigned char* lodepng_chunk_data(unsigned char* chunk); +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk); + +/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/ +unsigned lodepng_chunk_check_crc(const unsigned char* chunk); + +/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ +void lodepng_chunk_generate_crc(unsigned char* chunk); + +/* +Iterate to next chunks, allows iterating through all chunks of the PNG file. +Input must be at the beginning of a chunk (result of a previous lodepng_chunk_next call, +or the 8th byte of a PNG file which always has the first chunk), or alternatively may +point to the first byte of the PNG file (which is not a chunk but the magic header, the +function will then skip over it and return the first real chunk). +Will output pointer to the start of the next chunk, or at or beyond end of the file if there +is no more chunk after this or possibly if the chunk is corrupt. +Start this process at the 8th byte of the PNG file. +In a non-corrupt PNG file, the last chunk should have name "IEND". +*/ +unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end); +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end); + +/*Finds the first chunk with the given type in the range [chunk, end), or returns NULL if not found.*/ +unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]); +const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]); + +/* +Appends chunk to the data in out. The given chunk should already have its chunk header. +The out variable and outsize are updated to reflect the new reallocated buffer. +Returns error code (0 if it went ok) +*/ +unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk); + +/* +Appends new chunk to out. The chunk to append is given by giving its length, type +and data separately. The type is a 4-letter string. +The out variable and outsize are updated to reflect the new reallocated buffer. +Returne error code (0 if it went ok) +*/ +unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, unsigned length, + const char* type, const unsigned char* data); + + +/*Calculate CRC32 of buffer*/ +unsigned lodepng_crc32(const unsigned char* buf, size_t len); +#endif /*LODEPNG_COMPILE_PNG*/ + + +#ifdef LODEPNG_COMPILE_ZLIB +/* +This zlib part can be used independently to zlib compress and decompress a +buffer. It cannot be used to create gzip files however, and it only supports the +part of zlib that is required for PNG, it does not support dictionaries. +*/ + +#ifdef LODEPNG_COMPILE_DECODER +/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/ +unsigned lodepng_inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings); + +/* +Decompresses Zlib data. Reallocates the out buffer and appends the data. The +data must be according to the zlib specification. +Either, *out must be NULL and *outsize must be 0, or, *out must be a valid +buffer and *outsize its size in bytes. out must be freed by user after usage. +*/ +unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Compresses data with Zlib. Reallocates the out buffer and appends the data. +Zlib adds a small header and trailer around the deflate data. +The data is output in the format of the zlib specification. +Either, *out must be NULL and *outsize must be 0, or, *out must be a valid +buffer and *outsize its size in bytes. out must be freed by user after usage. +*/ +unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings); + +/* +Find length-limited Huffman code for given frequencies. This function is in the +public interface only for tests, it's used internally by lodepng_deflate. +*/ +unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, + size_t numcodes, unsigned maxbitlen); + +/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/ +unsigned lodepng_deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings); + +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_ZLIB*/ + +#ifdef LODEPNG_COMPILE_DISK +/* +Load a file from disk into buffer. The function allocates the out buffer, and +after usage you should free it. +out: output parameter, contains pointer to loaded buffer. +outsize: output parameter, size of the allocated out buffer +filename: the path to the file to load +return value: error code (0 means ok) + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory. +*/ +unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename); + +/* +Save a file from buffer to disk. Warning, if it exists, this function overwrites +the file without warning! +buffer: the buffer to write +buffersize: size of the buffer to write +filename: the path to the file to save to +return value: error code (0 means ok) + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and encode in-memory +*/ +unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename); +#endif /*LODEPNG_COMPILE_DISK*/ + +#ifdef LODEPNG_COMPILE_CPP +/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */ +namespace lodepng { +#ifdef LODEPNG_COMPILE_PNG +class State : public LodePNGState { + public: + State(); + State(const State& other); + ~State(); + State& operator=(const State& other); +}; + +#ifdef LODEPNG_COMPILE_DECODER +/* Same as other lodepng::decode, but using a State for more settings and information. */ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const unsigned char* in, size_t insize); +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const std::vector& in); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* Same as other lodepng::encode, but using a State for more settings and information. */ +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + State& state); +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + State& state); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DISK +/* +Load a file from disk into an std::vector. +return value: error code (0 means ok) + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and decode in-memory +*/ +unsigned load_file(std::vector& buffer, const std::string& filename); + +/* +Save the binary data in an std::vector to a file on disk. The file is overwritten +without warning. + +NOTE: Wide-character filenames are not supported, you can use an external method +to handle such files and encode in-memory +*/ +unsigned save_file(const std::vector& buffer, const std::string& filename); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_PNG */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_DECODER +/* Zlib-decompress an unsigned char buffer */ +unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); + +/* Zlib-decompress an std::vector */ +unsigned decompress(std::vector& out, const std::vector& in, + const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +/* Zlib-compress an unsigned char buffer */ +unsigned compress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings& settings = lodepng_default_compress_settings); + +/* Zlib-compress an std::vector */ +unsigned compress(std::vector& out, const std::vector& in, + const LodePNGCompressSettings& settings = lodepng_default_compress_settings); +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_ZLIB */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ + +/* +TODO: +[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often +[.] check compatibility with various compilers - done but needs to be redone for every newer version +[X] converting color to 16-bit per channel types +[X] support color profile chunk types (but never let them touch RGB values by default) +[ ] support all public PNG chunk types (almost done except sPLT and hIST) +[ ] make sure encoder generates no chunks with size > (2^31)-1 +[ ] partial decoding (stream processing) +[X] let the "isFullyOpaque" function check color keys and transparent palettes too +[X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl" +[ ] allow treating some errors like warnings, when image is recoverable (e.g. 69, 57, 58) +[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ... +[ ] error messages with line numbers (and version) +[ ] errors in state instead of as return code? +[ ] new errors/warnings like suspiciously big decompressed ztxt or iccp chunk +[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes +[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ... +[ ] allow user to give data (void*) to custom allocator +[X] provide alternatives for C library functions not present on some platforms (memcpy, ...) +*/ + +#endif /*LODEPNG_H inclusion guard*/ + +/* +LodePNG Documentation +--------------------- + +0. table of contents +-------------------- + + 1. about + 1.1. supported features + 1.2. features not supported + 2. C and C++ version + 3. security + 4. decoding + 5. encoding + 6. color conversions + 6.1. PNG color types + 6.2. color conversions + 6.3. padding bits + 6.4. A note about 16-bits per channel and endianness + 7. error values + 8. chunks and PNG editing + 9. compiler support + 10. examples + 10.1. decoder C++ example + 10.2. decoder C example + 11. state settings reference + 12. changes + 13. contact information + + +1. about +-------- + +PNG is a file format to store raster images losslessly with good compression, +supporting different color types and alpha channel. + +LodePNG is a PNG codec according to the Portable Network Graphics (PNG) +Specification (Second Edition) - W3C Recommendation 10 November 2003. + +The specifications used are: + +*) Portable Network Graphics (PNG) Specification (Second Edition): + http://www.w3.org/TR/2003/REC-PNG-20031110 +*) RFC 1950 ZLIB Compressed Data Format version 3.3: + http://www.gzip.org/zlib/rfc-zlib.html +*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3: + http://www.gzip.org/zlib/rfc-deflate.html + +The most recent version of LodePNG can currently be found at +http://lodev.org/lodepng/ + +LodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds +extra functionality. + +LodePNG exists out of two files: +-lodepng.h: the header file for both C and C++ +-lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage + +If you want to start using LodePNG right away without reading this doc, get the +examples from the LodePNG website to see how to use it in code, or check the +smaller examples in chapter 13 here. + +LodePNG is simple but only supports the basic requirements. To achieve +simplicity, the following design choices were made: There are no dependencies +on any external library. There are functions to decode and encode a PNG with +a single function call, and extended versions of these functions taking a +LodePNGState struct allowing to specify or get more information. By default +the colors of the raw image are always RGB or RGBA, no matter what color type +the PNG file uses. To read and write files, there are simple functions to +convert the files to/from buffers in memory. + +This all makes LodePNG suitable for loading textures in games, demos and small +programs, ... It's less suitable for full fledged image editors, loading PNGs +over network (it requires all the image data to be available before decoding can +begin), life-critical systems, ... + +1.1. supported features +----------------------- + +The following features are supported by the decoder: + +*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image, + or the same color type as the PNG +*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image +*) Adam7 interlace and deinterlace for any color type +*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk +*) support for alpha channels, including RGBA color model, translucent palettes and color keying +*) zlib decompression (inflate) +*) zlib compression (deflate) +*) CRC32 and ADLER32 checksums +*) colorimetric color profile conversions: currently experimentally available in lodepng_util.cpp only, + plus alternatively ability to pass on chroma/gamma/ICC profile information to other color management system. +*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks. +*) the following chunks are supported by both encoder and decoder: + IHDR: header information + PLTE: color palette + IDAT: pixel data + IEND: the final chunk + tRNS: transparency for palettized images + tEXt: textual information + zTXt: compressed textual information + iTXt: international textual information + bKGD: suggested background color + pHYs: physical dimensions + tIME: modification time + cHRM: RGB chromaticities + gAMA: RGB gamma correction + iCCP: ICC color profile + sRGB: rendering intent + sBIT: significant bits + +1.2. features not supported +--------------------------- + +The following features are not (yet) supported: + +*) some features needed to make a conformant PNG-Editor might be still missing. +*) partial loading/stream processing. All data must be available and is processed in one call. +*) The hIST and sPLT public chunks are not (yet) supported but treated as unknown chunks + + +2. C and C++ version +-------------------- + +The C version uses buffers allocated with alloc that you need to free() +yourself. You need to use init and cleanup functions for each struct whenever +using a struct from the C version to avoid exploits and memory leaks. + +The C++ version has extra functions with std::vectors in the interface and the +lodepng::State class which is a LodePNGState with constructor and destructor. + +These files work without modification for both C and C++ compilers because all +the additional C++ code is in "#ifdef __cplusplus" blocks that make C-compilers +ignore it, and the C code is made to compile both with strict ISO C90 and C++. + +To use the C++ version, you need to rename the source file to lodepng.cpp +(instead of lodepng.c), and compile it with a C++ compiler. + +To use the C version, you need to rename the source file to lodepng.c (instead +of lodepng.cpp), and compile it with a C compiler. + + +3. Security +----------- + +Even if carefully designed, it's always possible that LodePNG contains possible +exploits. If you discover one, please let me know, and it will be fixed. + +When using LodePNG, care has to be taken with the C version of LodePNG, as well +as the C-style structs when working with C++. The following conventions are used +for all C-style structs: + +-if a struct has a corresponding init function, always call the init function when making a new one +-if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks +-if a struct has a corresponding copy function, use the copy function instead of "=". + The destination must also be inited already. + + +4. Decoding +----------- + +Decoding converts a PNG compressed image to a raw pixel buffer. + +Most documentation on using the decoder is at its declarations in the header +above. For C, simple decoding can be done with functions such as +lodepng_decode32, and more advanced decoding can be done with the struct +LodePNGState and lodepng_decode. For C++, all decoding can be done with the +various lodepng::decode functions, and lodepng::State can be used for advanced +features. + +When using the LodePNGState, it uses the following fields for decoding: +*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here +*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get +*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use + +LodePNGInfo info_png +-------------------- + +After decoding, this contains extra information of the PNG image, except the actual +pixels, width and height because these are already gotten directly from the decoder +functions. + +It contains for example the original color type of the PNG image, text comments, +suggested background color, etc... More details about the LodePNGInfo struct are +at its declaration documentation. + +LodePNGColorMode info_raw +------------------------- + +When decoding, here you can specify which color type you want +the resulting raw image to be. If this is different from the colortype of the +PNG, then the decoder will automatically convert the result. This conversion +always works, except if you want it to convert a color PNG to grayscale or to +a palette with missing colors. + +By default, 32-bit color is used for the result. + +LodePNGDecoderSettings decoder +------------------------------ + +The settings can be used to ignore the errors created by invalid CRC and Adler32 +chunks, and to disable the decoding of tEXt chunks. + +There's also a setting color_convert, true by default. If false, no conversion +is done, the resulting data will be as it was in the PNG (after decompression) +and you'll have to puzzle the colors of the pixels together yourself using the +color type information in the LodePNGInfo. + + +5. Encoding +----------- + +Encoding converts a raw pixel buffer to a PNG compressed image. + +Most documentation on using the encoder is at its declarations in the header +above. For C, simple encoding can be done with functions such as +lodepng_encode32, and more advanced decoding can be done with the struct +LodePNGState and lodepng_encode. For C++, all encoding can be done with the +various lodepng::encode functions, and lodepng::State can be used for advanced +features. + +Like the decoder, the encoder can also give errors. However it gives less errors +since the encoder input is trusted, the decoder input (a PNG image that could +be forged by anyone) is not trusted. + +When using the LodePNGState, it uses the following fields for encoding: +*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be. +*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has +*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use + +LodePNGInfo info_png +-------------------- + +When encoding, you use this the opposite way as when decoding: for encoding, +you fill in the values you want the PNG to have before encoding. By default it's +not needed to specify a color type for the PNG since it's automatically chosen, +but it's possible to choose it yourself given the right settings. + +The encoder will not always exactly match the LodePNGInfo struct you give, +it tries as close as possible. Some things are ignored by the encoder. The +encoder uses, for example, the following settings from it when applicable: +colortype and bitdepth, text chunks, time chunk, the color key, the palette, the +background color, the interlace method, unknown chunks, ... + +When encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk. +If the palette contains any colors for which the alpha channel is not 255 (so +there are translucent colors in the palette), it'll add a tRNS chunk. + +LodePNGColorMode info_raw +------------------------- + +You specify the color type of the raw image that you give to the input here, +including a possible transparent color key and palette you happen to be using in +your raw image data. + +By default, 32-bit color is assumed, meaning your input has to be in RGBA +format with 4 bytes (unsigned chars) per pixel. + +LodePNGEncoderSettings encoder +------------------------------ + +The following settings are supported (some are in sub-structs): +*) auto_convert: when this option is enabled, the encoder will +automatically choose the smallest possible color mode (including color key) that +can encode the colors of all pixels without information loss. +*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree, + 2 = dynamic huffman tree (best compression). Should be 2 for proper + compression. +*) use_lz77: whether or not to use LZ77 for compressed block types. Should be + true for proper compression. +*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value + 2048 by default, but can be set to 32768 for better, but slow, compression. +*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE + chunk if force_palette is true. This can used as suggested palette to convert + to by viewers that don't support more than 256 colors (if those still exist) +*) add_id: add text chunk "Encoder: LodePNG " to the image. +*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks. + zTXt chunks use zlib compression on the text. This gives a smaller result on + large texts but a larger result on small texts (such as a single program name). + It's all tEXt or all zTXt though, there's no separate setting per text yet. + + +6. color conversions +-------------------- + +An important thing to note about LodePNG, is that the color type of the PNG, and +the color type of the raw image, are completely independent. By default, when +you decode a PNG, you get the result as a raw image in the color type you want, +no matter whether the PNG was encoded with a palette, grayscale or RGBA color. +And if you encode an image, by default LodePNG will automatically choose the PNG +color type that gives good compression based on the values of colors and amount +of colors in the image. It can be configured to let you control it instead as +well, though. + +To be able to do this, LodePNG does conversions from one color mode to another. +It can convert from almost any color type to any other color type, except the +following conversions: RGB to grayscale is not supported, and converting to a +palette when the palette doesn't have a required color is not supported. This is +not supported on purpose: this is information loss which requires a color +reduction algorithm that is beyond the scope of a PNG encoder (yes, RGB to gray +is easy, but there are multiple ways if you want to give some channels more +weight). + +By default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB +color, no matter what color type the PNG has. And by default when encoding, +LodePNG automatically picks the best color model for the output PNG, and expects +the input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control +the color format of the images yourself, you can skip this chapter. + +6.1. PNG color types +-------------------- + +A PNG image can have many color types, ranging from 1-bit color to 64-bit color, +as well as palettized color modes. After the zlib decompression and unfiltering +in the PNG image is done, the raw pixel data will have that color type and thus +a certain amount of bits per pixel. If you want the output raw image after +decoding to have another color type, a conversion is done by LodePNG. + +The PNG specification gives the following color types: + +0: grayscale, bit depths 1, 2, 4, 8, 16 +2: RGB, bit depths 8 and 16 +3: palette, bit depths 1, 2, 4 and 8 +4: grayscale with alpha, bit depths 8 and 16 +6: RGBA, bit depths 8 and 16 + +Bit depth is the amount of bits per pixel per color channel. So the total amount +of bits per pixel is: amount of channels * bitdepth. + +6.2. color conversions +---------------------- + +As explained in the sections about the encoder and decoder, you can specify +color types and bit depths in info_png and info_raw to change the default +behaviour. + +If, when decoding, you want the raw image to be something else than the default, +you need to set the color type and bit depth you want in the LodePNGColorMode, +or the parameters colortype and bitdepth of the simple decoding function. + +If, when encoding, you use another color type than the default in the raw input +image, you need to specify its color type and bit depth in the LodePNGColorMode +of the raw image, or use the parameters colortype and bitdepth of the simple +encoding function. + +If, when encoding, you don't want LodePNG to choose the output PNG color type +but control it yourself, you need to set auto_convert in the encoder settings +to false, and specify the color type you want in the LodePNGInfo of the +encoder (including palette: it can generate a palette if auto_convert is true, +otherwise not). + +If the input and output color type differ (whether user chosen or auto chosen), +LodePNG will do a color conversion, which follows the rules below, and may +sometimes result in an error. + +To avoid some confusion: +-the decoder converts from PNG to raw image +-the encoder converts from raw image to PNG +-the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image +-the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG +-when encoding, the color type in LodePNGInfo is ignored if auto_convert + is enabled, it is automatically generated instead +-when decoding, the color type in LodePNGInfo is set by the decoder to that of the original + PNG image, but it can be ignored since the raw image has the color type you requested instead +-if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion + between the color types is done if the color types are supported. If it is not + supported, an error is returned. If the types are the same, no conversion is done. +-even though some conversions aren't supported, LodePNG supports loading PNGs from any + colortype and saving PNGs to any colortype, sometimes it just requires preparing + the raw image correctly before encoding. +-both encoder and decoder use the same color converter. + +The function lodepng_convert does the color conversion. It is available in the +interface but normally isn't needed since the encoder and decoder already call +it. + +Non supported color conversions: +-color to grayscale when non-gray pixels are present: no error is thrown, but +the result will look ugly because only the red channel is taken (it assumes all +three channels are the same in this case so ignores green and blue). The reason +no error is given is to allow converting from three-channel grayscale images to +one-channel even if there are numerical imprecisions. +-anything to palette when the palette does not have an exact match for a from-color +in it: in this case an error is thrown + +Supported color conversions: +-anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA +-any gray or gray+alpha, to gray or gray+alpha +-anything to a palette, as long as the palette has the requested colors in it +-removing alpha channel +-higher to smaller bitdepth, and vice versa + +If you want no color conversion to be done (e.g. for speed or control): +-In the encoder, you can make it save a PNG with any color type by giving the +raw color mode and LodePNGInfo the same color mode, and setting auto_convert to +false. +-In the decoder, you can make it store the pixel data in the same color type +as the PNG has, by setting the color_convert setting to false. Settings in +info_raw are then ignored. + +6.3. padding bits +----------------- + +In the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines +have a bit amount that isn't a multiple of 8, then padding bits are used so that each +scanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output. +The raw input image you give to the encoder, and the raw output image you get from the decoder +will NOT have these padding bits, e.g. in the case of a 1-bit image with a width +of 7 pixels, the first pixel of the second scanline will the 8th bit of the first byte, +not the first bit of a new byte. + +6.4. A note about 16-bits per channel and endianness +---------------------------------------------------- + +LodePNG uses unsigned char arrays for 16-bit per channel colors too, just like +for any other color format. The 16-bit values are stored in big endian (most +significant byte first) in these arrays. This is the opposite order of the +little endian used by x86 CPU's. + +LodePNG always uses big endian because the PNG file format does so internally. +Conversions to other formats than PNG uses internally are not supported by +LodePNG on purpose, there are myriads of formats, including endianness of 16-bit +colors, the order in which you store R, G, B and A, and so on. Supporting and +converting to/from all that is outside the scope of LodePNG. + +This may mean that, depending on your use case, you may want to convert the big +endian output of LodePNG to little endian with a for loop. This is certainly not +always needed, many applications and libraries support big endian 16-bit colors +anyway, but it means you cannot simply cast the unsigned char* buffer to an +unsigned short* buffer on x86 CPUs. + + +7. error values +--------------- + +All functions in LodePNG that return an error code, return 0 if everything went +OK, or a non-zero code if there was an error. + +The meaning of the LodePNG error values can be retrieved with the function +lodepng_error_text: given the numerical error code, it returns a description +of the error in English as a string. + +Check the implementation of lodepng_error_text to see the meaning of each code. + +It is not recommended to use the numerical values to programmatically make +different decisions based on error types as the numbers are not guaranteed to +stay backwards compatible. They are for human consumption only. Programmatically +only 0 or non-0 matter. + + +8. chunks and PNG editing +------------------------- + +If you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG +editor that should follow the rules about handling of unknown chunks, or if your +program is able to read other types of chunks than the ones handled by LodePNG, +then that's possible with the chunk functions of LodePNG. + +A PNG chunk has the following layout: + +4 bytes length +4 bytes type name +length bytes data +4 bytes CRC + +8.1. iterating through chunks +----------------------------- + +If you have a buffer containing the PNG image data, then the first chunk (the +IHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the +signature of the PNG and are not part of a chunk. But if you start at byte 8 +then you have a chunk, and can check the following things of it. + +NOTE: none of these functions check for memory buffer boundaries. To avoid +exploits, always make sure the buffer contains all the data of the chunks. +When using lodepng_chunk_next, make sure the returned value is within the +allocated memory. + +unsigned lodepng_chunk_length(const unsigned char* chunk): + +Get the length of the chunk's data. The total chunk length is this length + 12. + +void lodepng_chunk_type(char type[5], const unsigned char* chunk): +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type): + +Get the type of the chunk or compare if it's a certain type + +unsigned char lodepng_chunk_critical(const unsigned char* chunk): +unsigned char lodepng_chunk_private(const unsigned char* chunk): +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk): + +Check if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are). +Check if the chunk is private (public chunks are part of the standard, private ones not). +Check if the chunk is safe to copy. If it's not, then, when modifying data in a critical +chunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your +program doesn't handle that type of unknown chunk. + +unsigned char* lodepng_chunk_data(unsigned char* chunk): +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk): + +Get a pointer to the start of the data of the chunk. + +unsigned lodepng_chunk_check_crc(const unsigned char* chunk): +void lodepng_chunk_generate_crc(unsigned char* chunk): + +Check if the crc is correct or generate a correct one. + +unsigned char* lodepng_chunk_next(unsigned char* chunk): +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk): + +Iterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these +functions do no boundary checking of the allocated data whatsoever, so make sure there is enough +data available in the buffer to be able to go to the next chunk. + +unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk): +unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, unsigned length, + const char* type, const unsigned char* data): + +These functions are used to create new chunks that are appended to the data in *out that has +length *outsize. The append function appends an existing chunk to the new data. The create +function creates a new chunk with the given parameters and appends it. Type is the 4-letter +name of the chunk. + +8.2. chunks in info_png +----------------------- + +The LodePNGInfo struct contains fields with the unknown chunk in it. It has 3 +buffers (each with size) to contain 3 types of unknown chunks: +the ones that come before the PLTE chunk, the ones that come between the PLTE +and the IDAT chunks, and the ones that come after the IDAT chunks. +It's necessary to make the distinction between these 3 cases because the PNG +standard forces to keep the ordering of unknown chunks compared to the critical +chunks, but does not force any other ordering rules. + +info_png.unknown_chunks_data[0] is the chunks before PLTE +info_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT +info_png.unknown_chunks_data[2] is the chunks after IDAT + +The chunks in these 3 buffers can be iterated through and read by using the same +way described in the previous subchapter. + +When using the decoder to decode a PNG, you can make it store all unknown chunks +if you set the option settings.remember_unknown_chunks to 1. By default, this +option is off (0). + +The encoder will always encode unknown chunks that are stored in the info_png. +If you need it to add a particular chunk that isn't known by LodePNG, you can +use lodepng_chunk_append or lodepng_chunk_create to the chunk data in +info_png.unknown_chunks_data[x]. + +Chunks that are known by LodePNG should not be added in that way. E.g. to make +LodePNG add a bKGD chunk, set background_defined to true and add the correct +parameters there instead. + + +9. compiler support +------------------- + +No libraries other than the current standard C library are needed to compile +LodePNG. For the C++ version, only the standard C++ library is needed on top. +Add the files lodepng.c(pp) and lodepng.h to your project, include +lodepng.h where needed, and your program can read/write PNG files. + +It is compatible with C90 and up, and C++03 and up. + +If performance is important, use optimization when compiling! For both the +encoder and decoder, this makes a large difference. + +Make sure that LodePNG is compiled with the same compiler of the same version +and with the same settings as the rest of the program, or the interfaces with +std::vectors and std::strings in C++ can be incompatible. + +CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets. + +*) gcc and g++ + +LodePNG is developed in gcc so this compiler is natively supported. It gives no +warnings with compiler options "-Wall -Wextra -pedantic -ansi", with gcc and g++ +version 4.7.1 on Linux, 32-bit and 64-bit. + +*) Clang + +Fully supported and warning-free. + +*) Mingw + +The Mingw compiler (a port of gcc for Windows) should be fully supported by +LodePNG. + +*) Visual Studio and Visual C++ Express Edition + +LodePNG should be warning-free with warning level W4. Two warnings were disabled +with pragmas though: warning 4244 about implicit conversions, and warning 4996 +where it wants to use a non-standard function fopen_s instead of the standard C +fopen. + +Visual Studio may want "stdafx.h" files to be included in each source file and +give an error "unexpected end of file while looking for precompiled header". +This is not standard C++ and will not be added to the stock LodePNG. You can +disable it for lodepng.cpp only by right clicking it, Properties, C/C++, +Precompiled Headers, and set it to Not Using Precompiled Headers there. + +NOTE: Modern versions of VS should be fully supported, but old versions, e.g. +VS6, are not guaranteed to work. + +*) Compilers on Macintosh + +LodePNG has been reported to work both with gcc and LLVM for Macintosh, both for +C and C++. + +*) Other Compilers + +If you encounter problems on any compilers, feel free to let me know and I may +try to fix it if the compiler is modern and standards compliant. + + +10. examples +------------ + +This decoder example shows the most basic usage of LodePNG. More complex +examples can be found on the LodePNG website. + +NOTE: these examples do not support wide-character filenames, you can use an +external method to handle such files and encode or decode in-memory + +10.1. decoder C++ example +------------------------- + +#include "lodepng.h" +#include + +int main(int argc, char *argv[]) { + const char* filename = argc > 1 ? argv[1] : "test.png"; + + //load and decode + std::vector image; + unsigned width, height; + unsigned error = lodepng::decode(image, width, height, filename); + + //if there's an error, display it + if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl; + + //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ... +} + +10.2. decoder C example +----------------------- + +#include "lodepng.h" + +int main(int argc, char *argv[]) { + unsigned error; + unsigned char* image; + size_t width, height; + const char* filename = argc > 1 ? argv[1] : "test.png"; + + error = lodepng_decode32_file(&image, &width, &height, filename); + + if(error) printf("decoder error %u: %s\n", error, lodepng_error_text(error)); + + / * use image here * / + + free(image); + return 0; +} + +11. state settings reference +---------------------------- + +A quick reference of some settings to set on the LodePNGState + +For decoding: + +state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums +state.decoder.zlibsettings.custom_...: use custom inflate function +state.decoder.ignore_crc: ignore CRC checksums +state.decoder.ignore_critical: ignore unknown critical chunks +state.decoder.ignore_end: ignore missing IEND chunk. May fail if this corruption causes other errors +state.decoder.color_convert: convert internal PNG color to chosen one +state.decoder.read_text_chunks: whether to read in text metadata chunks +state.decoder.remember_unknown_chunks: whether to read in unknown chunks +state.info_raw.colortype: desired color type for decoded image +state.info_raw.bitdepth: desired bit depth for decoded image +state.info_raw....: more color settings, see struct LodePNGColorMode +state.info_png....: no settings for decoder but ouput, see struct LodePNGInfo + +For encoding: + +state.encoder.zlibsettings.btype: disable compression by setting it to 0 +state.encoder.zlibsettings.use_lz77: use LZ77 in compression +state.encoder.zlibsettings.windowsize: tweak LZ77 windowsize +state.encoder.zlibsettings.minmatch: tweak min LZ77 length to match +state.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching +state.encoder.zlibsettings.lazymatching: try one more LZ77 matching +state.encoder.zlibsettings.custom_...: use custom deflate function +state.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png +state.encoder.filter_palette_zero: PNG filter strategy for palette +state.encoder.filter_strategy: PNG filter strategy to encode with +state.encoder.force_palette: add palette even if not encoding to one +state.encoder.add_id: add LodePNG identifier and version as a text chunk +state.encoder.text_compression: use compressed text chunks for metadata +state.info_raw.colortype: color type of raw input image you provide +state.info_raw.bitdepth: bit depth of raw input image you provide +state.info_raw: more color settings, see struct LodePNGColorMode +state.info_png.color.colortype: desired color type if auto_convert is false +state.info_png.color.bitdepth: desired bit depth if auto_convert is false +state.info_png.color....: more color settings, see struct LodePNGColorMode +state.info_png....: more PNG related settings, see struct LodePNGInfo + + +12. changes +----------- + +The version number of LodePNG is the date of the change given in the format +yyyymmdd. + +Some changes aren't backwards compatible. Those are indicated with a (!) +symbol. + +Not all changes are listed here, the commit history in github lists more: +https://github.com/lvandeve/lodepng + +*) 10 apr 2023: faster CRC32 implementation, but with larger lookup table. +*) 13 jun 2022: added support for the sBIT chunk. +*) 09 jan 2022: minor decoder speed improvements. +*) 27 jun 2021: added warnings that file reading/writing functions don't support + wide-character filenames (support for this is not planned, opening files is + not the core part of PNG decoding/decoding and is platform dependent). +*) 17 okt 2020: prevent decoding too large text/icc chunks by default. +*) 06 mar 2020: simplified some of the dynamic memory allocations. +*) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct + overflow checks. +*) 14 aug 2019: around 25% faster decoding thanks to huffman lookup tables. +*) 15 jun 2019: (!) auto_choose_color API changed (for bugfix: don't use palette + if gray ICC profile) and non-ICC LodePNGColorProfile renamed to + LodePNGColorStats. +*) 30 dec 2018: code style changes only: removed newlines before opening braces. +*) 10 sep 2018: added way to inspect metadata chunks without full decoding. +*) 19 aug 2018: (!) fixed color mode bKGD is encoded with and made it use + palette index in case of palette. +*) 10 aug 2018: (!) added support for gAMA, cHRM, sRGB and iCCP chunks. This + change is backwards compatible unless you relied on unknown_chunks for those. +*) 11 jun 2018: less restrictive check for pixel size integer overflow +*) 14 jan 2018: allow optionally ignoring a few more recoverable errors +*) 17 sep 2017: fix memory leak for some encoder input error cases +*) 27 nov 2016: grey+alpha auto color model detection bugfix +*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort). +*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within + the limits of pure C90). +*) 08 dec 2015: Made load_file function return error if file can't be opened. +*) 24 okt 2015: Bugfix with decoding to palette output. +*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding. +*) 24 aug 2014: Moved to github +*) 23 aug 2014: Reduced needless memory usage of decoder. +*) 28 jun 2014: Removed fix_png setting, always support palette OOB for + simplicity. Made ColorProfile public. +*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization. +*) 22 dec 2013: Power of two windowsize required for optimization. +*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key. +*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png). +*) 11 mar 2013: (!) Bugfix with custom free. Changed from "my" to "lodepng_" + prefix for the custom allocators and made it possible with a new #define to + use custom ones in your project without needing to change lodepng's code. +*) 28 jan 2013: Bugfix with color key. +*) 27 okt 2012: Tweaks in text chunk keyword length error handling. +*) 8 okt 2012: (!) Added new filter strategy (entropy) and new auto color mode. + (no palette). Better deflate tree encoding. New compression tweak settings. + Faster color conversions while decoding. Some internal cleanups. +*) 23 sep 2012: Reduced warnings in Visual Studio a little bit. +*) 1 sep 2012: (!) Removed #define's for giving custom (de)compression functions + and made it work with function pointers instead. +*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc + and free functions and toggle #defines from compiler flags. Small fixes. +*) 6 may 2012: (!) Made plugging in custom zlib/deflate functions more flexible. +*) 22 apr 2012: (!) Made interface more consistent, renaming a lot. Removed + redundant C++ codec classes. Reduced amount of structs. Everything changed, + but it is cleaner now imho and functionality remains the same. Also fixed + several bugs and shrunk the implementation code. Made new samples. +*) 6 nov 2011: (!) By default, the encoder now automatically chooses the best + PNG color model and bit depth, based on the amount and type of colors of the + raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color. +*) 9 okt 2011: simpler hash chain implementation for the encoder. +*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching. +*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking. + A bug with the PNG filtertype heuristic was fixed, so that it chooses much + better ones (it's quite significant). A setting to do an experimental, slow, + brute force search for PNG filter types is added. +*) 17 aug 2011: (!) changed some C zlib related function names. +*) 16 aug 2011: made the code less wide (max 120 characters per line). +*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors. +*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled. +*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman + to optimize long sequences of zeros. +*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and + LodePNG_InfoColor_canHaveAlpha functions for convenience. +*) 7 nov 2010: added LodePNG_error_text function to get error code description. +*) 30 okt 2010: made decoding slightly faster +*) 26 okt 2010: (!) changed some C function and struct names (more consistent). + Reorganized the documentation and the declaration order in the header. +*) 08 aug 2010: only changed some comments and external samples. +*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version. +*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers. +*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could + read by ignoring the problem but windows apps couldn't. +*) 06 jun 2008: added more error checks for out of memory cases. +*) 26 apr 2008: added a few more checks here and there to ensure more safety. +*) 06 mar 2008: crash with encoding of strings fixed +*) 02 feb 2008: support for international text chunks added (iTXt) +*) 23 jan 2008: small cleanups, and #defines to divide code in sections +*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor. +*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder. +*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added + Also various fixes, such as in the deflate and the padding bits code. +*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved + filtering code of encoder. +*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A + C++ wrapper around this provides an interface almost identical to before. + Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code + are together in these files but it works both for C and C++ compilers. +*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks +*) 30 aug 2007: bug fixed which makes this Borland C++ compatible +*) 09 aug 2007: some VS2005 warnings removed again +*) 21 jul 2007: deflate code placed in new namespace separate from zlib code +*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images +*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing + invalid std::vector element [0] fixed, and level 3 and 4 warnings removed +*) 02 jun 2007: made the encoder add a tag with version by default +*) 27 may 2007: zlib and png code separated (but still in the same file), + simple encoder/decoder functions added for more simple usage cases +*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69), + moved some examples from here to lodepng_examples.cpp +*) 12 may 2007: palette decoding bug fixed +*) 24 apr 2007: changed the license from BSD to the zlib license +*) 11 mar 2007: very simple addition: ability to encode bKGD chunks. +*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding + palettized PNG images. Plus little interface change with palette and texts. +*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes. + Fixed a bug where the end code of a block had length 0 in the Huffman tree. +*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented + and supported by the encoder, resulting in smaller PNGs at the output. +*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone. +*) 24 jan 2007: gave encoder an error interface. Added color conversion from any + greyscale type to 8-bit greyscale with or without alpha. +*) 21 jan 2007: (!) Totally changed the interface. It allows more color types + to convert to and is more uniform. See the manual for how it works now. +*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days: + encode/decode custom tEXt chunks, separate classes for zlib & deflate, and + at last made the decoder give errors for incorrect Adler32 or Crc. +*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel. +*) 29 dec 2006: Added support for encoding images without alpha channel, and + cleaned out code as well as making certain parts faster. +*) 28 dec 2006: Added "Settings" to the encoder. +*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now. + Removed some code duplication in the decoder. Fixed little bug in an example. +*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter. + Fixed a bug of the decoder with 16-bit per color. +*) 15 okt 2006: Changed documentation structure +*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the + given image buffer, however for now it's not compressed. +*) 08 sep 2006: (!) Changed to interface with a Decoder class +*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different + way. Renamed decodePNG to decodePNGGeneric. +*) 29 jul 2006: (!) Changed the interface: image info is now returned as a + struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy. +*) 28 jul 2006: Cleaned the code and added new error checks. + Corrected terminology "deflate" into "inflate". +*) 23 jun 2006: Added SDL example in the documentation in the header, this + example allows easy debugging by displaying the PNG and its transparency. +*) 22 jun 2006: (!) Changed way to obtain error value. Added + loadFile function for convenience. Made decodePNG32 faster. +*) 21 jun 2006: (!) Changed type of info vector to unsigned. + Changed position of palette in info vector. Fixed an important bug that + happened on PNGs with an uncompressed block. +*) 16 jun 2006: Internally changed unsigned into unsigned where + needed, and performed some optimizations. +*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them + in LodePNG namespace. Changed the order of the parameters. Rewrote the + documentation in the header. Renamed files to lodepng.cpp and lodepng.h +*) 22 apr 2006: Optimized and improved some code +*) 07 sep 2005: (!) Changed to std::vector interface +*) 12 aug 2005: Initial release (C++, decoder only) + + +13. contact information +----------------------- + +Feel free to contact me with suggestions, problems, comments, ... concerning +LodePNG. If you encounter a PNG image that doesn't work properly with this +decoder, feel free to send it and I'll use it to find and fix the problem. + +My email address is (puzzle the account and domain together with an @ symbol): +Domain: gmail dot com. +Account: lode dot vandevenne. + + +Copyright (c) 2005-2022 Lode Vandevenne +*/ diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/resources/mesh.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/resources/mesh.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,371 @@ +import std/strutils +import std/json +import std/logging +import std/tables +import std/strformat +import std/streams + +import ../mesh +import ../material +import ../core + +import ./image + +type + glTFHeader = object + magic: uint32 + version: uint32 + length: uint32 + glTFData = object + structuredContent: JsonNode + binaryBufferData: seq[uint8] + +const + JSON_CHUNK = 0x4E4F534A + BINARY_CHUNK = 0x004E4942 + ACCESSOR_TYPE_MAP = { + 5120: Int8, + 5121: UInt8, + 5122: Int16, + 5123: UInt16, + 5125: UInt32, + 5126: Float32, + }.toTable + SAMPLER_FILTER_MODE_MAP = { + 9728: VK_FILTER_NEAREST, + 9729: VK_FILTER_LINEAR, + 9984: VK_FILTER_NEAREST, + 9985: VK_FILTER_LINEAR, + 9986: VK_FILTER_NEAREST, + 9987: VK_FILTER_LINEAR, + }.toTable + SAMPLER_WRAP_MODE_MAP = { + 33071: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + 33648: VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, + 10497: VK_SAMPLER_ADDRESS_MODE_REPEAT + }.toTable + GLTF_MATERIAL_MAPPING = { + "color": "baseColorFactor", + "emissiveColor": "emissiveFactor", + "metallic": "metallicFactor", + "roughness", "roughnessFactor", + "baseTexture": "baseColorTexture", + "metallicRoughnessTexture": "metallicRoughnessTexture", + "normalTexture": "normalTexture", + "occlusionTexture": "occlusionTexture", + "emissiveTexture": "emissiveTexture", + }.toTable + +proc getGPUType(accessor: JsonNode, attribute: string): DataType = + # TODO: no full support for all datatypes that glTF may provide + # semicongine/core/gpu_data should maybe generated with macros to allow for all combinations + let componentType = ACCESSOR_TYPE_MAP[accessor["componentType"].getInt()] + let theType = accessor["type"].getStr() + case theType + of "SCALAR": + return componentType + of "VEC2": + case componentType + of UInt32: return Vec2U32 + of Float32: return Vec2F32 + else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") + of "VEC3": + case componentType + of UInt32: return Vec3U32 + of Float32: return Vec3F32 + else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") + of "VEC4": + case componentType + of UInt32: return Vec4U32 + of Float32: return Vec4F32 + else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") + of "MAT2": + case componentType + of Float32: return Vec4F32 + else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") + of "MAT3": + case componentType + of Float32: return Vec4F32 + else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") + of "MAT4": + case componentType + of Float32: return Vec4F32 + else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") + +proc getBufferViewData(bufferView: JsonNode, mainBuffer: seq[uint8], baseBufferOffset=0): seq[uint8] = + assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported" + + result = newSeq[uint8](bufferView["byteLength"].getInt()) + let bufferOffset = bufferView["byteOffset"].getInt() + baseBufferOffset + var dstPointer = addr result[0] + + if bufferView.hasKey("byteStride"): + raise newException(Exception, "Unsupported feature: byteStride in buffer view") + copyMem(dstPointer, addr mainBuffer[bufferOffset], result.len) + +proc getAccessorData(root: JsonNode, accessor: JsonNode, mainBuffer: seq[uint8]): DataList = + result = initDataList(thetype=accessor.getGPUType("??")) + result.setLen(accessor["count"].getInt()) + + let bufferView = root["bufferViews"][accessor["bufferView"].getInt()] + assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported" + + if accessor.hasKey("sparse"): + raise newException(Exception, "Sparce accessors are currently not implemented") + + let accessorOffset = if accessor.hasKey("byteOffset"): accessor["byteOffset"].getInt() else: 0 + let length = bufferView["byteLength"].getInt() + let bufferOffset = bufferView["byteOffset"].getInt() + accessorOffset + var dstPointer = result.getRawData()[0] + + if bufferView.hasKey("byteStride"): + warn "Congratulations, you try to test a feature (loading buffer data with stride attributes) that we have no idea where it is used and how it can be tested (need a coresponding *.glb file)." + # we don't support stride, have to convert stuff here... does this even work? + for i in 0 ..< int(result.len): + copyMem(dstPointer, addr mainBuffer[bufferOffset + i * bufferView["byteStride"].getInt()], int(result.thetype.size)) + dstPointer = cast[pointer](cast[int](dstPointer) + result.thetype.size) + else: + copyMem(dstPointer, addr mainBuffer[bufferOffset], length) + +proc loadImage(root: JsonNode, imageIndex: int, mainBuffer: seq[uint8]): Image = + if root["images"][imageIndex].hasKey("uri"): + raise newException(Exception, "Unsupported feature: Load images from external files") + + let bufferView = root["bufferViews"][root["images"][imageIndex]["bufferView"].getInt()] + let imgData = newStringStream(cast[string](getBufferViewData(bufferView, mainBuffer))) + + let imageType = root["images"][imageIndex]["mimeType"].getStr() + case imageType + of "image/bmp": + result = readBMP(imgData) + of "image/png": + result = readPNG(imgData) + else: + raise newException(Exception, "Unsupported feature: Load image of type " & imageType) + +proc loadTexture(root: JsonNode, textureIndex: int, mainBuffer: seq[uint8]): Texture = + let textureNode = root["textures"][textureIndex] + result.image = loadImage(root, textureNode["source"].getInt(), mainBuffer) + result.name = root["images"][textureNode["source"].getInt()]["name"].getStr() + if result.name == "": + result.name = &"Texture{textureIndex}" + + if textureNode.hasKey("sampler"): + let sampler = root["samplers"][textureNode["sampler"].getInt()] + if sampler.hasKey("magFilter"): + result.sampler.magnification = SAMPLER_FILTER_MODE_MAP[sampler["magFilter"].getInt()] + if sampler.hasKey("minFilter"): + result.sampler.minification = SAMPLER_FILTER_MODE_MAP[sampler["minFilter"].getInt()] + if sampler.hasKey("wrapS"): + result.sampler.wrapModeS = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()] + if sampler.hasKey("wrapT"): + result.sampler.wrapModeT = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()] + + +proc loadMaterial(root: JsonNode, materialNode: JsonNode, defaultMaterial: MaterialType, mainBuffer: seq[uint8]): MaterialData = + let pbr = materialNode["pbrMetallicRoughness"] + var attributes: Table[string, DataList] + + # color + if defaultMaterial.attributes.contains("color"): + attributes["color"] = initDataList(thetype=Vec4F32) + if pbr.hasKey(GLTF_MATERIAL_MAPPING["color"]): + setValue(attributes["color"], @[newVec4f( + pbr[GLTF_MATERIAL_MAPPING["color"]][0].getFloat(), + pbr[GLTF_MATERIAL_MAPPING["color"]][1].getFloat(), + pbr[GLTF_MATERIAL_MAPPING["color"]][2].getFloat(), + pbr[GLTF_MATERIAL_MAPPING["color"]][3].getFloat(), + )]) + else: + setValue(attributes["color"], @[newVec4f(1, 1, 1, 1)]) + + # pbr material values + for factor in ["metallic", "roughness"]: + if defaultMaterial.attributes.contains(factor): + attributes[factor] = initDataList(thetype=Float32) + if pbr.hasKey(GLTF_MATERIAL_MAPPING[factor]): + setValue(attributes[factor], @[float32(pbr[GLTF_MATERIAL_MAPPING[factor]].getFloat())]) + else: + setValue(attributes[factor], @[0.5'f32]) + + # pbr material textures + for texture in ["baseTexture", "metallicRoughnessTexture"]: + if defaultMaterial.attributes.contains(texture): + attributes[texture] = initDataList(thetype=TextureType) + # attributes[texture & "Index"] = initDataList(thetype=UInt8) + if pbr.hasKey(GLTF_MATERIAL_MAPPING[texture]): + setValue(attributes[texture], @[loadTexture(root, pbr[GLTF_MATERIAL_MAPPING[texture]]["index"].getInt(), mainBuffer)]) + # setValue(attributes[texture & "Index"], @[pbr[GLTF_MATERIAL_MAPPING[texture]].getOrDefault("texCoord").getInt(0).uint8]) + else: + setValue(attributes[texture], @[EMPTY_TEXTURE]) + # setValue(attributes[texture & "Index"], @[0'u8]) + + # generic material textures + for texture in ["normalTexture", "occlusionTexture", "emissiveTexture"]: + if defaultMaterial.attributes.contains(texture): + attributes[texture] = initDataList(thetype=TextureType) + # attributes[texture & "Index"] = initDataList(thetype=UInt8) + if materialNode.hasKey(GLTF_MATERIAL_MAPPING[texture]): + setValue(attributes[texture], @[loadTexture(root, materialNode[texture]["index"].getInt(), mainBuffer)]) + # setValue(attributes[texture & "Index"], @[materialNode[texture].getOrDefault("texCoord").getInt(0).uint8]) + else: + setValue(attributes[texture], @[EMPTY_TEXTURE]) + # setValue(attributes[texture & "Index"], @[0'u8]) + + # emissiv color + if defaultMaterial.attributes.contains("emissiveColor"): + attributes["emissiveColor"] = initDataList(thetype=Vec3F32) + if materialNode.hasKey(GLTF_MATERIAL_MAPPING["emissiveColor"]): + setValue(attributes["emissiveColor"], @[newVec3f( + materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][0].getFloat(), + materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][1].getFloat(), + materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][2].getFloat(), + )]) + else: + setValue(attributes["emissiveColor"], @[newVec3f(1'f32, 1'f32, 1'f32)]) + + result = initMaterialData(materialType=defaultMaterial, name=materialNode["name"].getStr(), attributes=attributes) + +proc loadMesh(meshname: string, root: JsonNode, primitiveNode: JsonNode, defaultMaterial: MaterialType, mainBuffer: seq[uint8]): Mesh = + if primitiveNode.hasKey("mode") and primitiveNode["mode"].getInt() != 4: + raise newException(Exception, "Currently only TRIANGLE mode is supported for geometry mode") + + var indexType = None + let indexed = primitiveNode.hasKey("indices") + if indexed: + # TODO: Tiny indices + var indexCount = root["accessors"][primitiveNode["indices"].getInt()]["count"].getInt() + if indexCount < int(high(uint16)): + indexType = Small + else: + indexType = Big + + result = Mesh( + instanceTransforms: @[Unit4F32], + indexType: indexType, + name: meshname, + vertexCount: 0, + ) + + for attribute, accessor in primitiveNode["attributes"].pairs: + let data = root.getAccessorData(root["accessors"][accessor.getInt()], mainBuffer) + if result.vertexCount == 0: + result.vertexCount = data.len + assert data.len == result.vertexCount + result[].initVertexAttribute(attribute.toLowerAscii, data) + + if primitiveNode.hasKey("material"): + let materialId = primitiveNode["material"].getInt() + result[].material = loadMaterial(root, root["materials"][materialId], defaultMaterial, mainBuffer) + else: + result[].material = EMPTY_MATERIAL.initMaterialData() + + if primitiveNode.hasKey("indices"): + assert result[].indexType != None + let data = root.getAccessorData(root["accessors"][primitiveNode["indices"].getInt()], mainBuffer) + var tri: seq[int] + case data.thetype + of UInt16: + for entry in getValues[uint16](data)[]: + tri.add int(entry) + if tri.len == 3: + # FYI gltf uses counter-clockwise indexing + result[].appendIndicesData(tri[0], tri[1], tri[2]) + tri.setLen(0) + of UInt32: + for entry in getValues[uint32](data)[]: + tri.add int(entry) + if tri.len == 3: + # FYI gltf uses counter-clockwise indexing + result[].appendIndicesData(tri[0], tri[1], tri[2]) + tri.setLen(0) + else: + raise newException(Exception, &"Unsupported index data type: {data.thetype}") + # TODO: getting from gltf to vulkan system is still messed up somehow, see other TODO + transform[Vec3f](result[], "position", scale(1, -1, 1)) + +proc loadNode(root: JsonNode, node: JsonNode, defaultMaterial: MaterialType, mainBuffer: var seq[uint8]): MeshTree = + result = MeshTree() + # mesh + if node.hasKey("mesh"): + let mesh = root["meshes"][node["mesh"].getInt()] + for primitive in mesh["primitives"]: + result.children.add MeshTree(mesh: loadMesh(mesh["name"].getStr(), root, primitive, defaultMaterial, mainBuffer)) + + # transformation + if node.hasKey("matrix"): + var mat: Mat4 + for i in 0 ..< node["matrix"].len: + mat[i] = node["matrix"][i].getFloat() + result.transform = mat + else: + var (t, r, s) = (Unit4F32, Unit4F32, Unit4F32) + if node.hasKey("translation"): + t = translate( + float32(node["translation"][0].getFloat()), + float32(node["translation"][1].getFloat()), + float32(node["translation"][2].getFloat()) + ) + if node.hasKey("rotation"): + t = rotate( + float32(node["rotation"][3].getFloat()), + newVec3f( + float32(node["rotation"][0].getFloat()), + float32(node["rotation"][1].getFloat()), + float32(node["rotation"][2].getFloat()) + ) + ) + if node.hasKey("scale"): + t = scale( + float32(node["scale"][0].getFloat()), + float32(node["scale"][1].getFloat()), + float32(node["scale"][2].getFloat()) + ) + result.transform = t * r * s + result.transform = scale(1, -1, 1) * result.transform + + # children + if node.hasKey("children"): + for childNode in node["children"]: + result.children.add loadNode(root, root["nodes"][childNode.getInt()], defaultMaterial, mainBuffer) + +proc loadMeshTree(root: JsonNode, scenenode: JsonNode, defaultMaterial: MaterialType, mainBuffer: var seq[uint8]): MeshTree = + result = MeshTree() + for nodeId in scenenode["nodes"]: + result.children.add loadNode(root, root["nodes"][nodeId.getInt()], defaultMaterial, mainBuffer) + # TODO: getting from gltf to vulkan system is still messed up somehow (i.e. not consistent for different files), see other TODO + # result.transform = scale(1, -1, 1) + result.updateTransforms() + + +proc readglTF*(stream: Stream, defaultMaterial: MaterialType): seq[MeshTree] = + var + header: glTFHeader + data: glTFData + + for name, value in fieldPairs(header): + stream.read(value) + + assert header.magic == 0x46546C67 + assert header.version == 2 + + var chunkLength = stream.readUint32() + assert stream.readUint32() == JSON_CHUNK + data.structuredContent = parseJson(stream.readStr(int(chunkLength))) + + chunkLength = stream.readUint32() + assert stream.readUint32() == BINARY_CHUNK + data.binaryBufferData.setLen(chunkLength) + assert stream.readData(addr data.binaryBufferData[0], int(chunkLength)) == int(chunkLength) + + # check that the refered buffer is the same as the binary chunk + # external binary buffers are not supported + assert data.structuredContent["buffers"].len == 1 + assert not data.structuredContent["buffers"][0].hasKey("uri") + let bufferLenDiff = int(chunkLength) - data.structuredContent["buffers"][0]["byteLength"].getInt() + assert 0 <= bufferLenDiff <= 3 # binary buffer may be aligned to 4 bytes + + debug "Loading mesh: ", data.structuredContent.pretty + + for scenedata in data.structuredContent["scenes"]: + result.add data.structuredContent.loadMeshTree(scenedata, defaultMaterial, data.binaryBufferData) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/resources/stb_truetype.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/resources/stb_truetype.h Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,5077 @@ +// stb_truetype.h - v1.26 - public domain +// authored from 2009-2021 by Sean Barrett / RAD Game Tools +// +// ======================================================================= +// +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES +// +// This library does no range checking of the offsets found in the file, +// meaning an attacker can use it to read arbitrary memory. +// +// ======================================================================= +// +// This library processes TrueType files: +// parse files +// extract glyph metrics +// extract glyph shapes +// render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) +// +// Todo: +// non-MS cmaps +// crashproof on bad data +// hinting? (no longer patented) +// cleartype-style AA? +// optimize: use simple memory allocator for intermediates +// optimize: build edge-list directly from curves +// optimize: rasterize directly from curves? +// +// ADDITIONAL CONTRIBUTORS +// +// Mikko Mononen: compound shape support, more cmap formats +// Tor Andersson: kerning, subpixel rendering +// Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning +// +// Misc other: +// Ryan Gordon +// Simon Glass +// github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel +// +// Bug/warning reports/fixes: +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) +// +// VERSION HISTORY +// +// 1.26 (2021-08-28) fix broken rasterizer +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// variant PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// +// Full history can be found at the end of this file. +// +// LICENSE +// +// See end of file for license information. +// +// USAGE +// +// Include this file in whatever places need to refer to it. In ONE C/C++ +// file, write: +// #define STB_TRUETYPE_IMPLEMENTATION +// before the #include of this file. This expands out the actual +// implementation into that C/C++ file. +// +// To make the implementation private to the file that generates the implementation, +// #define STBTT_STATIC +// +// Simple 3D API (don't ship this, but it's fine for tools and quick start) +// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture +// stbtt_GetBakedQuad() -- compute quad to draw for a given char +// +// Improved 3D API (more shippable): +// #include "stb_rect_pack.h" -- optional, but you really want it +// stbtt_PackBegin() +// stbtt_PackSetOversampling() -- for improved quality on small fonts +// stbtt_PackFontRanges() -- pack and renders +// stbtt_PackEnd() +// stbtt_GetPackedQuad() +// +// "Load" a font file from a memory buffer (you have to keep the buffer loaded) +// stbtt_InitFont() +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections +// +// Render a unicode codepoint to a bitmap +// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap +// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide +// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be +// +// Character advance/positioning +// stbtt_GetCodepointHMetrics() +// stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() +// stbtt_GetCodepointKernAdvance() +// +// Starting with version 1.06, the rasterizer was replaced with a new, +// faster and generally-more-precise rasterizer. The new rasterizer more +// accurately measures pixel coverage for anti-aliasing, except in the case +// where multiple shapes overlap, in which case it overestimates the AA pixel +// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If +// this turns out to be a problem, you can re-enable the old rasterizer with +// #define STBTT_RASTERIZER_VERSION 1 +// which will incur about a 15% speed hit. +// +// ADDITIONAL DOCUMENTATION +// +// Immediately after this block comment are a series of sample programs. +// +// After the sample programs is the "header file" section. This section +// includes documentation for each API function. +// +// Some important concepts to understand to use this library: +// +// Codepoint +// Characters are defined by unicode codepoints, e.g. 65 is +// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is +// the hiragana for "ma". +// +// Glyph +// A visual character shape (every codepoint is rendered as +// some glyph) +// +// Glyph index +// A font-specific integer ID representing a glyph +// +// Baseline +// Glyph shapes are defined relative to a baseline, which is the +// bottom of uppercase characters. Characters extend both above +// and below the baseline. +// +// Current Point +// As you draw text to the screen, you keep track of a "current point" +// which is the origin of each character. The current point's vertical +// position is the baseline. Even "baked fonts" use this model. +// +// Vertical Font Metrics +// The vertical qualities of the font, used to vertically position +// and space the characters. See docs for stbtt_GetFontVMetrics. +// +// Font Size in Pixels or Points +// The preferred interface for specifying font sizes in stb_truetype +// is to specify how tall the font's vertical extent should be in pixels. +// If that sounds good enough, skip the next paragraph. +// +// Most font APIs instead use "points", which are a common typographic +// measurement for describing font size, defined as 72 points per inch. +// stb_truetype provides a point API for compatibility. However, true +// "per inch" conventions don't make much sense on computer displays +// since different monitors have different number of pixels per +// inch. For example, Windows traditionally uses a convention that +// there are 96 pixels per inch, thus making 'inch' measurements have +// nothing to do with inches, and thus effectively defining a point to +// be 1.333 pixels. Additionally, the TrueType font data provides +// an explicit scale factor to scale a given font's glyphs to points, +// but the author has observed that this scale factor is often wrong +// for non-commercial fonts, thus making fonts scaled in points +// according to the TrueType spec incoherently sized in practice. +// +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to = 32 && *text < 128) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); + } + ++text; + } + glEnd(); +} +#endif +// +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program (this compiles): get a single bitmap, print as ASCII art +// +#if 0 +#include +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1<<25]; + +int main(int argc, char **argv) +{ + stbtt_fontinfo font; + unsigned char *bitmap; + int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); + + fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); + + stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); + bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) + putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); + putchar('\n'); + } + return 0; +} +#endif +// +// Output: +// +// .ii. +// @@@@@@. +// V@Mio@@o +// :i. V@V +// :oM@@M +// :@@@MM@M +// @@o o@M +// :@@. M@M +// @@@o@@@@ +// :M@@V:@@. +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program: print "Hello World!" banner, with bugs +// +#if 0 +char buffer[24<<20]; +unsigned char screen[20][79]; + +int main(int arg, char **argv) +{ + stbtt_fontinfo font; + int i,j,ascent,baseline,ch=0; + float scale, xpos=2; // leave a little padding in case the character extends left + char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness + + fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); + stbtt_InitFont(&font, buffer, 0); + + scale = stbtt_ScaleForPixelHeight(&font, 15); + stbtt_GetFontVMetrics(&font, &ascent,0,0); + baseline = (int) (ascent*scale); + + while (text[ch]) { + int advance,lsb,x0,y0,x1,y1; + float x_shift = xpos - (float) floor(xpos); + stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); + stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); + stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); + // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong + // because this API is really for baking character bitmaps into textures. if you want to render + // a sequence of characters, you really need to render each bitmap to a temp buffer, then + // "alpha blend" that into the working buffer + xpos += (advance * scale); + if (text[ch+1]) + xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); + ++ch; + } + + for (j=0; j < 20; ++j) { + for (i=0; i < 78; ++i) + putchar(" .:ioVM@"[screen[j][i]>>5]); + putchar('\n'); + } + + return 0; +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// INTEGRATION WITH YOUR CODEBASE +//// +//// The following sections allow you to supply alternate definitions +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. + +#ifdef STB_TRUETYPE_IMPLEMENTATION + // #define your own (u)stbtt_int8/16/32 before including to override this + #ifndef stbtt_uint8 + typedef unsigned char stbtt_uint8; + typedef signed char stbtt_int8; + typedef unsigned short stbtt_uint16; + typedef signed short stbtt_int16; + typedef unsigned int stbtt_uint32; + typedef signed int stbtt_int32; + #endif + + typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; + typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; + + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + #ifndef STBTT_ifloor + #include + #define STBTT_ifloor(x) ((int) floor(x)) + #define STBTT_iceil(x) ((int) ceil(x)) + #endif + + #ifndef STBTT_sqrt + #include + #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) + #endif + + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h + #ifndef STBTT_malloc + #include + #define STBTT_malloc(x,u) ((void)(u),malloc(x)) + #define STBTT_free(x,u) ((void)(u),free(x)) + #endif + + #ifndef STBTT_assert + #include + #define STBTT_assert(x) assert(x) + #endif + + #ifndef STBTT_strlen + #include + #define STBTT_strlen(x) strlen(x) + #endif + + #ifndef STBTT_memcpy + #include + #define STBTT_memcpy memcpy + #define STBTT_memset memset + #endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// INTERFACE +//// +//// + +#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ +#define __STB_INCLUDE_STB_TRUETYPE_H__ + +#ifdef STBTT_STATIC +#define STBTT_DEF static +#else +#define STBTT_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// private structure +typedef struct +{ + unsigned char *data; + int cursor; + int size; +} stbtt__buf; + +////////////////////////////////////////////////////////////////////////////// +// +// TEXTURE BAKING API +// +// If you use this API, you only have to call two functions ever. +// + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; +} stbtt_bakedchar; + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long +// if return is positive, the first unused row of the bitmap +// if return is negative, returns the negative of the number of characters that fit +// if return is 0, no characters fit and no rows were used +// This uses a very crappy packing. + +typedef struct +{ + float x0,y0,s0,t0; // top-left + float x1,y1,s1,t1; // bottom-right +} stbtt_aligned_quad; + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier +// Call GetBakedQuad with char_index = 'character - first_char', and it +// creates the quad you need to draw and advances the current position. +// +// The coordinate system used assumes y increases downwards. +// +// Characters will extend both above and below the current position; +// see discussion of "BASELINE" above. +// +// It's inefficient; you might want to c&p it and optimize it. + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); +// Query the font vertical metrics without having to create a font first. + + +////////////////////////////////////////////////////////////////////////////// +// +// NEW TEXTURE BAKING API +// +// This provides options for packing multiple fonts into one atlas, not +// perfectly but better than nothing. + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; + float xoff2,yoff2; +} stbtt_packedchar; + +typedef struct stbtt_pack_context stbtt_pack_context; +typedef struct stbtt_fontinfo stbtt_fontinfo; +#ifndef STB_RECT_PACK_VERSION +typedef struct stbrp_rect stbrp_rect; +#endif + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); +// Initializes a packing context stored in the passed-in stbtt_pack_context. +// Future calls using this context will pack characters into the bitmap passed +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is +// the distance from one row to the next (or 0 to mean they are packed tightly +// together). "padding" is the amount of padding to leave between each +// character (normally you want '1' for bitmaps you'll use as textures with +// bilinear filtering). +// +// Returns 0 on failure, 1 on success. + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); +// Cleans up the packing context and frees all memory. + +#define STBTT_POINT_SIZE(x) (-(x)) + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); +// Creates character bitmaps from the font_index'th font found in fontdata (use +// font_index=0 if you don't know what that is). It creates num_chars_in_range +// bitmaps for characters with unicode values starting at first_unicode_char_in_range +// and increasing. Data for how to render them is stored in chardata_for_range; +// pass these to stbtt_GetPackedQuad to get back renderable quads. +// +// font_size is the full height of the character from ascender to descender, +// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed +// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() +// and pass that result as 'font_size': +// ..., 20 , ... // font max minus min y is 20 pixels tall +// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall + +typedef struct +{ + float font_size; + int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint + int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints + int num_chars; + stbtt_packedchar *chardata_for_range; // output + unsigned char h_oversample, v_oversample; // don't set these, they're used internally +} stbtt_pack_range; + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +// Creates character bitmaps from multiple ranges of characters stored in +// ranges. This will usually create a better-packed bitmap than multiple +// calls to stbtt_PackFontRange. Note that you can call this multiple +// times within a single PackBegin/PackEnd. + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); +// Oversampling a font increases the quality by allowing higher-quality subpixel +// positioning, and is especially valuable at smaller text sizes. +// +// This function sets the amount of oversampling for all following calls to +// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given +// pack context. The default (no oversampling) is achieved by h_oversample=1 +// and v_oversample=1. The total number of pixels required is +// h_oversample*v_oversample larger than the default; for example, 2x2 +// oversampling requires 4x the storage of 1x1. For best results, render +// oversampled textures with bilinear filtering. Look at the readme in +// stb/tests/oversample for information about oversampled fonts +// +// To use with PackFontRangesGather etc., you must set it before calls +// call to PackFontRangesGatherRects. + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); +// If skip != 0, this tells stb_truetype to skip any codepoints for which +// there is no corresponding glyph. If skip=0, which is the default, then +// codepoints without a glyph recived the font's "missing character" glyph, +// typically an empty box by convention. + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int align_to_integer); + +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +// Calling these functions in sequence is roughly equivalent to calling +// stbtt_PackFontRanges(). If you more control over the packing of multiple +// fonts, or if you want to pack custom data into a font texture, take a look +// at the source to of stbtt_PackFontRanges() and create a custom version +// using these functions, e.g. call GatherRects multiple times, +// building up a single array of rects, then call PackRects once, +// then call RenderIntoRects repeatedly. This may result in a +// better packing than calling PackFontRanges multiple times +// (or it may not). + +// this is an opaque structure that you shouldn't mess with which holds +// all the context needed from PackBegin to PackEnd. +struct stbtt_pack_context { + void *user_allocator_context; + void *pack_info; + int width; + int height; + int stride_in_bytes; + int padding; + int skip_missing; + unsigned int h_oversample, v_oversample; + unsigned char *pixels; + void *nodes; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// FONT LOADING +// +// + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); +// Each .ttf/.ttc file may have more than one font. Each font has a sequential +// index number starting from 0. Call this function to get the font offset for +// a given index; it returns -1 if the index is out of range. A regular .ttf +// file will only define one font and it always be at offset 0, so it will +// return '0' for index 0, and -1 for all other indices. + +// The following structure is defined publicly so you can declare one on +// the stack or as a global or etc, but you should treat it as opaque. +struct stbtt_fontinfo +{ + void * userdata; + unsigned char * data; // pointer to .ttf file + int fontstart; // offset of start of font + + int numGlyphs; // number of glyphs, needed for range checking + + int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict +}; + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); +// Given an offset into the file that defines a font, this function builds +// the necessary cached info for the rest of the system. You must allocate +// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't +// need to do anything special to free it, because the contents are pure +// value data with no additional data structures. Returns 0 on failure. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER TO GLYPH-INDEX CONVERSIOn + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); +// If you're going to perform multiple operations on the same character +// and you want a speed-up, call this function with the character you're +// going to process, then use glyph-based functions instead of the +// codepoint-based functions. +// Returns 0 if the character codepoint is not defined in the font. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER PROPERTIES +// + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose "height" is 'pixels' tall. +// Height is measured as the distance from the highest ascender to the lowest +// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics +// and computing: +// scale = pixels / (ascent - descent) +// so if you prefer to measure height by the ascent only, use a similar calculation. + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose EM size is mapped to +// 'pixels' tall. This is probably what traditional APIs compute, but +// I'm not positive. + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); +// ascent is the coordinate above the baseline the font extends; descent +// is the coordinate below the baseline the font extends (i.e. it is typically negative) +// lineGap is the spacing between one row's descent and the next row's ascent... +// so you should advance the vertical position by "*ascent - *descent + *lineGap" +// these are expressed in unscaled coordinates, so you must multiply by +// the scale factor for a given size + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); +// the bounding box around all possible characters + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); +// leftSideBearing is the offset from the current horizontal position to the left edge of the character +// advanceWidth is the offset from the current horizontal position to the next horizontal position +// these are expressed in unscaled coordinates + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); +// an additional amount to add to the 'advance' value between ch1 and ch2 + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); +// Gets the bounding box of the visible part of the glyph, in unscaled coordinates + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); +// as above, but takes one or more glyph indices for greater efficiency + +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) + +////////////////////////////////////////////////////////////////////////////// +// +// GLYPH SHAPES (you probably don't need these, but they have to go before +// the bitmaps for C declaration-order reasons) +// + +#ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum { + STBTT_vmove=1, + STBTT_vline, + STBTT_vcurve, + STBTT_vcubic + }; +#endif + +#ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) + #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x,y,cx,cy,cx1,cy1; + unsigned char type,padding; + } stbtt_vertex; +#endif + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); +// returns non-zero if nothing is drawn for this glyph + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); +// returns # of vertices and fills *vertices with the pointer to them +// these are expressed in "unscaled" coordinates +// +// The shape is a series of contours. Each one starts with +// a STBTT_moveto, then consists of a series of mixed +// STBTT_lineto and STBTT_curveto segments. A lineto +// draws a line from previous endpoint to its x,y; a curveto +// draws a quadratic bezier from previous endpoint to +// its x,y, using cx,cy as the bezier control point. + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); +// frees the data allocated above + +STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + +////////////////////////////////////////////////////////////////////////////// +// +// BITMAP RENDERING +// + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); +// frees the bitmap allocated below + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// allocates a large-enough single-channel 8bpp bitmap and renders the +// specified character/glyph at the specified scale into it, with +// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). +// *width & *height are filled out with the width & height of the bitmap, +// which is stored left-to-right, top-to-bottom. +// +// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); +// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap +// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap +// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the +// width and height and positioning info for it first. + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); +// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +// get the bbox of the bitmap centered around the glyph origin; so the +// bitmap width is ix1-ix0, height is iy1-iy0, and location to place +// the bitmap top left is (leftSideBearing*scale,iy0). +// (Note that the bitmap uses y-increases-down, but the shape uses +// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel +// shift for the character + +// the following functions are equivalent to the above functions, but operate +// on glyph indices instead of Unicode codepoints (for efficiency) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + + +// @TODO: don't expose this structure +typedef struct +{ + int w,h,stride; + unsigned char *pixels; +} stbtt__bitmap; + +// rasterize a shape with quadratic beziers into a bitmap +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex *vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC + +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + +////////////////////////////////////////////////////////////////////////////// +// +// Finding the right font... +// +// You should really just solve this offline, keep your own tables +// of what font is what, and don't try to get it out of the .ttf file. +// That's because getting it out of the .ttf file is really hard, because +// the names in the file can appear in many possible encodings, in many +// possible languages, and e.g. if you need a case-insensitive comparison, +// the details of that depend on the encoding & language in a complex way +// (actually underspecified in truetype, but also gigantic). +// +// But you can use the provided functions in two possible ways: +// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on +// unicode-encoded names to try to find the font you want; +// you can run this before calling stbtt_InitFont() +// +// stbtt_GetFontNameString() lets you get any of the various strings +// from the file yourself and do your own comparisons on them. +// You have to have called stbtt_InitFont() first. + + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); +// returns the offset (not index) of the font that matches, or -1 if none +// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". +// if you use any other flag, use a font name like "Arial"; this checks +// the 'macStyle' header field; i don't know if fonts set this consistently +#define STBTT_MACSTYLE_DONTCARE 0 +#define STBTT_MACSTYLE_BOLD 1 +#define STBTT_MACSTYLE_ITALIC 2 +#define STBTT_MACSTYLE_UNDERSCORE 4 +#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); +// returns 1/0 whether the first string interpreted as utf8 is identical to +// the second string interpreted as big-endian utf16... useful for strings from next func + +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); +// returns the string (which may be big-endian double byte, e.g. for unicode) +// and puts the length in bytes in *length. +// +// some of the values for the IDs are below; for more see the truetype spec: +// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html +// http://www.microsoft.com/typography/otspec/name.htm + +enum { // platformID + STBTT_PLATFORM_ID_UNICODE =0, + STBTT_PLATFORM_ID_MAC =1, + STBTT_PLATFORM_ID_ISO =2, + STBTT_PLATFORM_ID_MICROSOFT =3 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 =0, + STBTT_UNICODE_EID_UNICODE_1_1 =1, + STBTT_UNICODE_EID_ISO_10646 =2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL =0, + STBTT_MS_EID_UNICODE_BMP =1, + STBTT_MS_EID_SHIFTJIS =2, + STBTT_MS_EID_UNICODE_FULL =10 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, + STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, + STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, + STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 +}; + +enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, + STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, + STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, + STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, + STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, + STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D +}; + +enum { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, + STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, + STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, + STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , + STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , + STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, + STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 +}; + +#ifdef __cplusplus +} +#endif + +#endif // __STB_INCLUDE_STB_TRUETYPE_H__ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// IMPLEMENTATION +//// +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +#ifndef STBTT_MAX_OVERSAMPLE +#define STBTT_MAX_OVERSAMPLE 8 +#endif + +#if STBTT_MAX_OVERSAMPLE > 255 +#error "STBTT_MAX_OVERSAMPLE cannot be > 255" +#endif + +typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; + +#ifndef STBTT_RASTERIZER_VERSION +#define STBTT_RASTERIZER_VERSION 2 +#endif + +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + +////////////////////////////////////////////////////////////////////////// +// +// accessors to parse data from file +// + +// on platforms that don't allow misaligned reads, if we want to allow +// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE + +#define ttBYTE(p) (* (stbtt_uint8 *) (p)) +#define ttCHAR(p) (* (stbtt_int8 *) (p)) +#define ttFixed(p) ttLONG(p) + +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + +#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) +#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + +static int stbtt__isfont(stbtt_uint8 *font) +{ + // check the version number + if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts + return 0; +} + +// @OPTIMIZE: binary search +static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) +{ + stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + for (i=0; i < num_tables; ++i) { + stbtt_uint32 loc = tabledir + 16*i; + if (stbtt_tag(data+loc+0, tag)) + return ttULONG(data+loc+8); + } + return 0; +} + +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) +{ + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) + return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + stbtt_int32 n = ttLONG(font_collection+8); + if (index >= n) + return -1; + return ttULONG(font_collection+12+index*4); + } + } + return -1; +} + +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return 0; +} + +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + +// since most people won't use this, find this table the first time it's needed +static int stbtt__get_svg(stbtt_fontinfo *info) +{ + stbtt_uint32 t; + if (info->svg < 0) { + t = stbtt__find_table(info->data, info->fontstart, "SVG "); + if (t) { + stbtt_uint32 offset = ttULONG(info->data + t + 2); + info->svg = t + offset; + } else { + info->svg = 0; + } + } + return info->svg; +} + +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) +{ + stbtt_uint32 cmap, t; + stbtt_int32 i,numTables; + + info->data = data; + info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); + + cmap = stbtt__find_table(data, fontstart, "cmap"); // required + info->loca = stbtt__find_table(data, fontstart, "loca"); // required + info->head = stbtt__find_table(data, fontstart, "head"); // required + info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required + info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required + info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required + info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required + + if (!cmap || !info->head || !info->hhea || !info->hmtx) + return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, 512*1024*1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } + + t = stbtt__find_table(data, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data+t+4); + else + info->numGlyphs = 0xffff; + + info->svg = -1; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i=0; i < numTables; ++i) { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch(ttUSHORT(data+encoding_record)) { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data+encoding_record+2)) { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + break; + case STBTT_PLATFORM_ID_UNICODE: + // Mac/iOS has these + // all the encodingIDs are unicode, so we don't bother to check it + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + } + if (info->index_map == 0) + return 0; + + info->indexToLocFormat = ttUSHORT(data+info->head + 50); + return 1; +} + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +{ + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes-6) + return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } else if (format == 6) { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); + return 0; + } else if (format == 2) { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); + stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) + return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) + search += rangeShift*2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) { + stbtt_uint16 end; + searchRange >>= 1; + end = ttUSHORT(data + search + searchRange*2); + if (unicode_codepoint > end) + search += searchRange*2; + --entrySelector; + } + search += 2; + + { + stbtt_uint16 offset, start, last; + stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); + + start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); + last = ttUSHORT(data + endCount + 2*item); + if (unicode_codepoint < start || unicode_codepoint > last) + return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); + if (offset == 0) + return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); + + return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + } + } else if (format == 12 || format == 13) { + stbtt_uint32 ngroups = ttULONG(data+index_map+12); + stbtt_int32 low,high; + low = 0; high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low < high) { + stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); + stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); + if ((stbtt_uint32) unicode_codepoint < start_char) + high = mid; + else if ((stbtt_uint32) unicode_codepoint > end_char) + low = mid+1; + else { + stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); + if (format == 12) + return start_glyph + unicode_codepoint-start_char; + else // format == 13 + return start_glyph; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; +} + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) +{ + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); +} + +static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) +{ + v->type = type; + v->x = (stbtt_int16) x; + v->y = (stbtt_int16) y; + v->cx = (stbtt_int16) cx; + v->cy = (stbtt_int16) cy; +} + +static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) +{ + int g1,g2; + + STBTT_assert(!info->cff.size); + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + + if (info->indexToLocFormat == 0) { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } else { + g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); + } + + return g1==g2 ? -1 : g1; // if length is 0, return -1 +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } + return 1; +} + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +{ + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); +} + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt_int16 numberOfContours; + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 1; + numberOfContours = ttSHORT(info->data + g); + return numberOfContours == 0; +} + +static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, + stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) +{ + if (start_off) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); + } + return num_vertices; +} + +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + stbtt_int16 numberOfContours; + stbtt_uint8 *endPtsOfContours; + stbtt_uint8 *data = info->data; + stbtt_vertex *vertices=0; + int num_vertices=0; + int g = stbtt__GetGlyfOffset(info, glyph_index); + + *pvertices = NULL; + + if (g < 0) return 0; + + numberOfContours = ttSHORT(data + g); + + if (numberOfContours > 0) { + stbtt_uint8 flags=0,flagcount; + stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; + stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; + + n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); + + m = n + 2*numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) + return 0; + + next_move = 0; + flagcount=0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i=0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } else + --flagcount; + vertices[off+i].type = flags; + } + + // now load x coordinates + x=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 2) { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } else { + if (!(flags & 16)) { + x = x + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].x = (stbtt_int16) x; + } + + // now load y coordinates + y=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 4) { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } else { + if (!(flags & 32)) { + y = y + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].y = (stbtt_int16) y; + } + + // now convert them to our format + num_vertices=0; + sx = sy = cx = cy = scx = scy = 0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + x = (stbtt_int16) vertices[off+i].x; + y = (stbtt_int16) vertices[off+i].y; + + if (next_move == i) { + if (i != 0) + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(vertices[off+i+1].type & 1)) { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; + sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; + } else { + // otherwise just use the next point as our start point + sx = (stbtt_int32) vertices[off+i+1].x; + sy = (stbtt_int32) vertices[off+i+1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } else { + sx = x; + sy = y; + } + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); + was_off = 0; + next_move = 1 + ttUSHORT(endPtsOfContours+j*2); + ++j; + } else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); + was_off = 0; + } + } + } + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + } else if (numberOfContours < 0) { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + num_vertices = 0; + vertices = 0; + while (more) { + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + stbtt_vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = {1,0,0,1,0,0}, m, n; + + flags = ttSHORT(comp); comp+=2; + gidx = ttSHORT(comp); comp+=2; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + mtx[4] = ttSHORT(comp); comp+=2; + mtx[5] = ttSHORT(comp); comp+=2; + } else { + mtx[4] = ttCHAR(comp); comp+=1; + mtx[5] = ttCHAR(comp); comp+=1; + } + } + else { + // @TODO handle matching point + STBTT_assert(0); + } + if (flags & (1<<3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } + + // Find transformation scales. + m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); + n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + if (comp_num_verts > 0) { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + stbtt_vertex_type x,y; + x=v->x; y=v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + x=v->cx; y=v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + } + // Append vertices. + tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); + if (!tmp) { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1<<5); + } + } else { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; +} + +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // FALLTHROUGH + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && b0 < 32) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); +} + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +{ + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); + } else { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); + } +} + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint8 *data = info->data + info->kern; + stbtt_uint32 needle, straw; + int l, r, m; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + l = 0; + r = ttUSHORT(data+10) - 1; + needle = glyph1 << 16 | glyph2; + while (l <= r) { + m = (l + r) >> 1; + straw = ttULONG(data+18+(m*6)); // note: unaligned read + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else + return ttSHORT(data+22+(m*6)); + } + return 0; +} + +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch (coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + break; + } + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + break; + } + + default: return -1; // unsupported + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch (classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + break; + } + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + break; + } + + default: + return -1; // Unsupported definition type, return an error. + } + + // "All glyphs not assigned to a class fall into class 0". (OpenType spec) + return 0; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i, sti; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i= pairSetCount) return 0; + + needle=glyph2; + r=pairValueCount-1; + l=0; + + // Binary search. + while (l <= r) { + stbtt_uint16 secondGlyph; + stbtt_uint8 *pairValue; + m = (l + r) >> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } else + return 0; + break; + } + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + stbtt_uint8 *class1Records, *class2Records; + stbtt_int16 xAdvance; + + if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed + if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed + + class1Records = table + 16; + class2Records = class1Records + 2 * (glyph1class * class2Count); + xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } else + return 0; + break; + } + + default: + return 0; // Unsupported position format + } + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + else if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +{ + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs + return 0; + return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); +} + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +{ + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); +} + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +{ + if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); + if (descent) *descent = ttSHORT(info->data+info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); +} + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) +{ + *x0 = ttSHORT(info->data + info->head + 36); + *y0 = ttSHORT(info->data + info->head + 38); + *x1 = ttSHORT(info->data + info->head + 40); + *y1 = ttSHORT(info->data + info->head + 42); +} + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float) height / fheight; +} + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) +{ + int unitsPerEm = ttUSHORT(info->data + info->head + 18); + return pixels / unitsPerEm; +} + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +{ + STBTT_free(v, info->userdata); +} + +STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) +{ + int i; + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); + + int numEntries = ttUSHORT(svg_doc_list); + stbtt_uint8 *svg_docs = svg_doc_list + 2; + + for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) + return svg_doc; + } + return 0; +} + +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) +{ + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc; + + if (info->svg == 0) + return 0; + + svg_doc = stbtt_FindSVGDoc(info, gl); + if (svg_doc != NULL) { + *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); + return ttULONG(svg_doc + 8); + } else { + return 0; + } +} + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) +{ + return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); +} + +////////////////////////////////////////////////////////////////////////////// +// +// antialiasing software rasterizer +// + +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning + if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { + // e.g. space character + if (ix0) *ix0 = 0; + if (iy0) *iy0 = 0; + if (ix1) *ix1 = 0; + if (iy1) *iy1 = 0; + } else { + // move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); + if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); + if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); + if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); + } +} + +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); +} + +////////////////////////////////////////////////////////////////////////////// +// +// Rasterizer + +typedef struct stbtt__hheap_chunk +{ + struct stbtt__hheap_chunk *next; +} stbtt__hheap_chunk; + +typedef struct stbtt__hheap +{ + struct stbtt__hheap_chunk *head; + void *first_free; + int num_remaining_in_head_chunk; +} stbtt__hheap; + +static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) +{ + if (hh->first_free) { + void *p = hh->first_free; + hh->first_free = * (void **) p; + return p; + } else { + if (hh->num_remaining_in_head_chunk == 0) { + int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + if (c == NULL) + return NULL; + c->next = hh->head; + hh->head = c; + hh->num_remaining_in_head_chunk = count; + } + --hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; + } +} + +static void stbtt__hheap_free(stbtt__hheap *hh, void *p) +{ + *(void **) p = hh->first_free; + hh->first_free = p; +} + +static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) +{ + stbtt__hheap_chunk *c = hh->head; + while (c) { + stbtt__hheap_chunk *n = c->next; + STBTT_free(c, userdata); + c = n; + } +} + +typedef struct stbtt__edge { + float x0,y0, x1,y1; + int invert; +} stbtt__edge; + + +typedef struct stbtt__active_edge +{ + struct stbtt__active_edge *next; + #if STBTT_RASTERIZER_VERSION==1 + int x,dx; + float ey; + int direction; + #elif STBTT_RASTERIZER_VERSION==2 + float fx,fdx,fdy; + float direction; + float sy; + float ey; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif +} stbtt__active_edge; + +#if STBTT_RASTERIZER_VERSION == 1 +#define STBTT_FIXSHIFT 10 +#define STBTT_FIX (1 << STBTT_FIXSHIFT) +#define STBTT_FIXMASK (STBTT_FIX-1) + +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + if (!z) return z; + + // round dx down to avoid overshooting + if (dxdy < 0) + z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); + else + z->dx = STBTT_ifloor(STBTT_FIX * dxdy); + + z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount + z->x -= off_x * STBTT_FIX; + + z->ey = e->y1; + z->next = 0; + z->direction = e->invert ? 1 : -1; + return z; +} +#elif STBTT_RASTERIZER_VERSION == 2 +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + //STBTT_assert(e->y0 <= start_point); + if (!z) return z; + z->fdx = dxdy; + z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; + z->fx = e->x0 + dxdy * (start_point - e->y0); + z->fx -= off_x; + z->direction = e->invert ? 1.0f : -1.0f; + z->sy = e->y0; + z->ey = e->y1; + z->next = 0; + return z; +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#if STBTT_RASTERIZER_VERSION == 1 +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) +{ + // non-zero winding fill + int x0=0, w=0; + + while (e) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->direction; + } else { + int x1 = e->x; w += e->direction; + // if we went to zero, we need to draw + if (w == 0) { + int i = x0 >> STBTT_FIXSHIFT; + int j = x1 >> STBTT_FIXSHIFT; + + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8) max_weight; + } + } + } + } + + e = e->next; + } +} + +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *) STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; + + while (j < result->h) { + STBTT_memset(scanline, 0, result->w); + for (s=0; s < vsubsample; ++s) { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for(;;) { + int changed=0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) { + if (e->y1 > scan_y) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + } + ++e; + } + + // now process all active edges in XOR fashion + if (active) + stbtt__fill_active_edges(scanline, result->w, active, max_weight); + + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} + +#elif STBTT_RASTERIZER_VERSION == 2 + +// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 +// (i.e. it has already been clipped to those) +static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) +{ + if (y0 == y1) return; + STBTT_assert(y0 < y1); + STBTT_assert(e->sy <= e->ey); + if (y0 > e->ey) return; + if (y1 < e->sy) return; + if (y0 < e->sy) { + x0 += (x1-x0) * (e->sy - y0) / (y1-y0); + y0 = e->sy; + } + if (y1 > e->ey) { + x1 += (x1-x0) * (e->ey - y1) / (y1-y0); + y1 = e->ey; + } + + if (x0 == x) + STBTT_assert(x1 <= x+1); + else if (x0 == x+1) + STBTT_assert(x1 >= x); + else if (x0 <= x) + STBTT_assert(x1 <= x); + else if (x0 >= x+1) + STBTT_assert(x1 >= x+1); + else + STBTT_assert(x1 >= x && x1 <= x+1); + + if (x0 <= x && x1 <= x) + scanline[x] += e->direction * (y1-y0); + else if (x0 >= x+1 && x1 >= x+1) + ; + else { + STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); + scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position + } +} + +static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) +{ + STBTT_assert(top_width >= 0); + STBTT_assert(bottom_width >= 0); + return (top_width + bottom_width) / 2.0f * height; +} + +static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) +{ + return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); +} + +static float stbtt__sized_triangle_area(float height, float width) +{ + return height * width / 2; +} + +static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) +{ + float y_bottom = y_top+1; + + while (e) { + // brute force every pixel + + // compute intersection points with top & bottom + STBTT_assert(e->ey >= y_top); + + if (e->fdx == 0) { + float x0 = e->fx; + if (x0 < len) { + if (x0 >= 0) { + stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); + stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); + } else { + stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); + } + } + } else { + float x0 = e->fx; + float dx = e->fdx; + float xb = x0 + dx; + float x_top, x_bottom; + float sy0,sy1; + float dy = e->fdy; + STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); + + // compute endpoints of line segment clipped to this scanline (if the + // line segment starts on this scanline. x0 is the intersection of the + // line with y_top, but that may be off the line segment. + if (e->sy > y_top) { + x_top = x0 + dx * (e->sy - y_top); + sy0 = e->sy; + } else { + x_top = x0; + sy0 = y_top; + } + if (e->ey < y_bottom) { + x_bottom = x0 + dx * (e->ey - y_top); + sy1 = e->ey; + } else { + x_bottom = xb; + sy1 = y_bottom; + } + + if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { + // from here on, we don't have to range check x values + + if ((int) x_top == (int) x_bottom) { + float height; + // simple case, only spans one pixel + int x = (int) x_top; + height = (sy1 - sy0) * e->direction; + STBTT_assert(x >= 0 && x < len); + scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); + scanline_fill[x] += height; // everything right of this pixel is filled + } else { + int x,x1,x2; + float y_crossing, y_final, step, sign, area; + // covers 2+ pixels + if (x_top > x_bottom) { + // flip scanline vertically; signed area is the same + float t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; + t = x_bottom, x_bottom = x_top, x_top = t; + dx = -dx; + dy = -dy; + t = x0, x0 = xb, xb = t; + } + STBTT_assert(dy >= 0); + STBTT_assert(dx >= 0); + + x1 = (int) x_top; + x2 = (int) x_bottom; + // compute intersection with y axis at x1+1 + y_crossing = y_top + dy * (x1+1 - x0); + + // compute intersection with y axis at x2 + y_final = y_top + dy * (x2 - x0); + + // x1 x_top x2 x_bottom + // y_top +------|-----+------------+------------+--------|---+------------+ + // | | | | | | + // | | | | | | + // sy0 | Txxxxx|............|............|............|............| + // y_crossing | *xxxxx.......|............|............|............| + // | | xxxxx..|............|............|............| + // | | /- xx*xxxx........|............|............| + // | | dy < | xxxxxx..|............|............| + // y_final | | \- | xx*xxx.........|............| + // sy1 | | | | xxxxxB...|............| + // | | | | | | + // | | | | | | + // y_bottom +------------+------------+------------+------------+------------+ + // + // goal is to measure the area covered by '.' in each pixel + + // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 + // @TODO: maybe test against sy1 rather than y_bottom? + if (y_crossing > y_bottom) + y_crossing = y_bottom; + + sign = e->direction; + + // area of the rectangle covered from sy0..y_crossing + area = sign * (y_crossing-sy0); + + // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) + scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); + + // check if final y_crossing is blown up; no test case for this + if (y_final > y_bottom) { + y_final = y_bottom; + dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom + } + + // in second pixel, area covered by line segment found in first pixel + // is always a rectangle 1 wide * the height of that line segment; this + // is exactly what the variable 'area' stores. it also gets a contribution + // from the line segment within it. the THIRD pixel will get the first + // pixel's rectangle contribution, the second pixel's rectangle contribution, + // and its own contribution. the 'own contribution' is the same in every pixel except + // the leftmost and rightmost, a trapezoid that slides down in each pixel. + // the second pixel's contribution to the third pixel will be the + // rectangle 1 wide times the height change in the second pixel, which is dy. + + step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x, + // which multiplied by 1-pixel-width is how much pixel area changes for each step in x + // so the area advances by 'step' every time + + for (x = x1+1; x < x2; ++x) { + scanline[x] += area + step/2; // area of trapezoid is 1*step/2 + area += step; + } + STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down + STBTT_assert(sy1 > y_final-0.01f); + + // area covered in the last pixel is the rectangle from all the pixels to the left, + // plus the trapezoid filled by the line segment in this pixel all the way to the right edge + scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); + + // the rest of the line is filled based on the total height of the line segment in this pixel + scanline_fill[x2] += sign * (sy1-sy0); + } + } else { + // if edge goes outside of box we're drawing, we require + // clipping logic. since this does not match the intended use + // of this library, we use a different, very slow brute + // force implementation + // note though that this does happen some of the time because + // x_top and x_bottom can be extrapolated at the top & bottom of + // the shape and actually lie outside the bounding box + int x; + for (x=0; x < len; ++x) { + // cases: + // + // there can be up to two intersections with the pixel. any intersection + // with left or right edges can be handled by splitting into two (or three) + // regions. intersections with top & bottom do not necessitate case-wise logic. + // + // the old way of doing this found the intersections with the left & right edges, + // then used some simple logic to produce up to three segments in sorted order + // from top-to-bottom. however, this had a problem: if an x edge was epsilon + // across the x border, then the corresponding y position might not be distinct + // from the other y segment, and it might ignored as an empty segment. to avoid + // that, we need to explicitly produce segments based on x positions. + + // rename variables to clearly-defined pairs + float y0 = y_top; + float x1 = (float) (x); + float x2 = (float) (x+1); + float x3 = xb; + float y3 = y_bottom; + + // x = e->x + e->dx * (y-y_top) + // (y-y_top) = (x - e->x) / e->dx + // y = (x - e->x) / e->dx + y_top + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; + + if (x0 < x1 && x3 > x2) { // three segments descending down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x1 && x0 > x2) { // three segments descending down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else { // one segment + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); + } + } + } + } + e = e->next; + } +} + +// directly AA rasterize edges w/o supersampling +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0, i; + float scanline_data[129], *scanline, *scanline2; + + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) + scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); + else + scanline = scanline_data; + + scanline2 = scanline + result->w; + + y = off_y; + e[n].y0 = (float) (off_y + result->h) + 1; + + while (j < result->h) { + // find center of pixel for this scanline + float scan_y_top = y + 0.0f; + float scan_y_bottom = y + 1.0f; + stbtt__active_edge **step = &active; + + STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); + STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); + + // update all active edges; + // remove all active edges that terminate before the top of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y_top) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + step = &((*step)->next); // advance through list + } + } + + // insert all edges that start before the bottom of this scanline + while (e->y0 <= scan_y_bottom) { + if (e->y0 != e->y1) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + if (z != NULL) { + if (j == 0 && off_y != 0) { + if (z->ey < scan_y_top) { + // this can happen due to subpixel positioning and some kind of fp rounding error i think + z->ey = scan_y_top; + } + } + STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds + // insert at front + z->next = active; + active = z; + } + } + ++e; + } + + // now process all active edges + if (active) + stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); + + { + float sum = 0; + for (i=0; i < result->w; ++i) { + float k; + int m; + sum += scanline2[i]; + k = scanline[i] + sum; + k = (float) STBTT_fabs(k)*255 + 0.5f; + m = (int) k; + if (m > 255) m = 255; + result->pixels[j*result->stride + i] = (unsigned char) m; + } + } + // advance all the edges + step = &active; + while (*step) { + stbtt__active_edge *z = *step; + z->fx += z->fdx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + + ++y; + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) + +static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) +{ + int i,j; + for (i=1; i < n; ++i) { + stbtt__edge t = p[i], *a = &t; + j = i; + while (j > 0) { + stbtt__edge *b = &p[j-1]; + int c = STBTT__COMPARE(a,b); + if (!c) break; + p[j] = p[j-1]; + --j; + } + if (i != j) + p[j] = t; + } +} + +static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) +{ + /* threshold for transitioning to insertion sort */ + while (n > 12) { + stbtt__edge t; + int c01,c12,c,m,i,j; + + /* compute median of three */ + m = n >> 1; + c01 = STBTT__COMPARE(&p[0],&p[m]); + c12 = STBTT__COMPARE(&p[m],&p[n-1]); + /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ + if (c01 != c12) { + /* otherwise, we'll need to swap something else to middle */ + int z; + c = STBTT__COMPARE(&p[0],&p[n-1]); + /* 0>mid && midn => n; 0 0 */ + /* 0n: 0>n => 0; 0 n */ + z = (c == c12) ? 0 : n-1; + t = p[z]; + p[z] = p[m]; + p[m] = t; + } + /* now p[m] is the median-of-three */ + /* swap it to the beginning so it won't move around */ + t = p[0]; + p[0] = p[m]; + p[m] = t; + + /* partition loop */ + i=1; + j=n-1; + for(;;) { + /* handling of equality is crucial here */ + /* for sentinels & efficiency with duplicates */ + for (;;++i) { + if (!STBTT__COMPARE(&p[i], &p[0])) break; + } + for (;;--j) { + if (!STBTT__COMPARE(&p[0], &p[j])) break; + } + /* make sure we haven't crossed */ + if (i >= j) break; + t = p[i]; + p[i] = p[j]; + p[j] = t; + + ++i; + --j; + } + /* recurse on smaller side, iterate on larger */ + if (j < (n-i)) { + stbtt__sort_edges_quicksort(p,j); + p = p+i; + n = n-i; + } else { + stbtt__sort_edges_quicksort(p+i, n-i); + n = j; + } + } +} + +static void stbtt__sort_edges(stbtt__edge *p, int n) +{ + stbtt__sort_edges_quicksort(p, n); + stbtt__sort_edges_ins_sort(p, n); +} + +typedef struct +{ + float x,y; +} stbtt__point; + +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n,i,j,k,m; +#if STBTT_RASTERIZER_VERSION == 1 + int vsubsample = result->h < 8 ? 15 : 5; +#elif STBTT_RASTERIZER_VERSION == 2 + int vsubsample = 1; +#else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i=0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m=0; + for (i=0; i < windings; ++i) { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i]-1; + for (k=0; k < wcount[i]; j=k++) { + int a=k,b=j; + // skip the edge if horizontal + if (p[j].y == p[k].y) + continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { + e[n].invert = 1; + a=j,b=k; + } + e[n].x0 = p[a].x * scale_x + shift_x; + e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; + e[n].x1 = p[b].x * scale_x + shift_x; + e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + stbtt__sort_edges(e, n); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); +} + +static void stbtt__add_point(stbtt__point *points, int n, float x, float y) +{ + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; +} + +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2*x1 + x2)/4; + float my = (y0 + 2*y1 + y2)/4; + // versus directly drawn line + float dx = (x0+x2)/2 - mx; + float dy = (y0+y2)/2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x2,y2); + *num_points = *num_points+1; + } + return 1; +} + +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); + float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + +// returns number of contours +static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +{ + stbtt__point *points=0; + int num_points=0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i,n=0,start=0, pass; + + // count how many "moves" there are to get the contour count + for (i=0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) + ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass=0; pass < 2; ++pass) { + float x=0,y=0; + if (pass == 1) { + points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n= -1; + for (i=0; i < num_verts; ++i) { + switch (vertices[i].type) { + case STBTT_vmove: + // start the next contour + if (n >= 0) + (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x,y); + break; + case STBTT_vline: + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vcurve: + stbtt__tesselate_curve(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } + + return points; +error: + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } +} + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + int ix0,iy0,ix1,iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) { + STBTT_free(vertices, info->userdata); + return NULL; + } + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); + + // now we get the size + gbm.w = (ix1 - ix0); + gbm.h = (iy1 - iy0); + gbm.pixels = NULL; // in case we error + + if (width ) *width = gbm.w; + if (height) *height = gbm.h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + if (gbm.w && gbm.h) { + gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); + if (gbm.pixels) { + gbm.stride = gbm.w; + + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +{ + int ix0,iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + stbtt__bitmap gbm; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; + + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); + + STBTT_free(vertices, info->userdata); +} + +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +{ + stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); +} + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-CRAPPY packing to keep source code small + +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x,y,bottom_y, i; + stbtt_fontinfo f; + f.userdata = NULL; + if (!stbtt_InitFont(&f, data, offset)) + return -1; + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + x=y=1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i=0; i < num_chars; ++i) { + int advance, lsb, x0,y0,x1,y1,gw,gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); + gw = x1-x0; + gh = y1-y0; + if (x + gw + 1 >= pw) + y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x+gw < pw); + STBTT_assert(y+gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + chardata[i].x0 = (stbtt_int16) x; + chardata[i].y0 = (stbtt_int16) y; + chardata[i].x1 = (stbtt_int16) (x + gw); + chardata[i].y1 = (stbtt_int16) (y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float) x0; + chardata[i].yoff = (float) y0; + x = x + gw + 1; + if (y+gh+1 > bottom_y) + bottom_y = y+gh+1; + } + return bottom_y; +} + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +{ + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); + + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// rectangle packing replacement routines if you don't have stb_rect_pack.h +// + +#ifndef STB_RECT_PACK_VERSION + +typedef int stbrp_coord; + +//////////////////////////////////////////////////////////////////////////////////// +// // +// // +// COMPILER WARNING ?!?!? // +// // +// // +// if you get a compile warning due to these symbols being defined more than // +// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // +// // +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int width,height; + int x,y,bottom_y; +} stbrp_context; + +typedef struct +{ + unsigned char x; +} stbrp_node; + +struct stbrp_rect +{ + stbrp_coord x,y; + int id,w,h,was_packed; +}; + +static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) +{ + con->width = pw; + con->height = ph; + con->x = 0; + con->y = 0; + con->bottom_y = 0; + STBTT__NOTUSED(nodes); + STBTT__NOTUSED(num_nodes); +} + +static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) +{ + int i; + for (i=0; i < num_rects; ++i) { + if (con->x + rects[i].w > con->width) { + con->x = 0; + con->y = con->bottom_y; + } + if (con->y + rects[i].h > con->height) + break; + rects[i].x = con->x; + rects[i].y = con->y; + rects[i].was_packed = 1; + con->x += rects[i].w; + if (con->y + rects[i].h > con->bottom_y) + con->bottom_y = con->y + rects[i].h; + } + for ( ; i < num_rects; ++i) + rects[i].was_packed = 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If +// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) +{ + stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); + int num_nodes = pw - padding; + stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + + if (context == NULL || nodes == NULL) { + if (context != NULL) STBTT_free(context, alloc_context); + if (nodes != NULL) STBTT_free(nodes , alloc_context); + return 0; + } + + spc->user_allocator_context = alloc_context; + spc->width = pw; + spc->height = ph; + spc->pixels = pixels; + spc->pack_info = context; + spc->nodes = nodes; + spc->padding = padding; + spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; + spc->h_oversample = 1; + spc->v_oversample = 1; + spc->skip_missing = 0; + + stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); + + if (pixels) + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + + return 1; +} + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) +{ + STBTT_free(spc->nodes , spc->user_allocator_context); + STBTT_free(spc->pack_info, spc->user_allocator_context); +} + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) +{ + STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); + STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); + if (h_oversample <= STBTT_MAX_OVERSAMPLE) + spc->h_oversample = h_oversample; + if (v_oversample <= STBTT_MAX_OVERSAMPLE) + spc->v_oversample = v_oversample; +} + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) +{ + spc->skip_missing = skip; +} + +#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) + +static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_w = w - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < h; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < w; ++i) { + STBTT_assert(pixels[i] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i] = (unsigned char) (total / kernel_width); + } + + pixels += stride_in_bytes; + } +} + +static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_h = h - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < w; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < h; ++i) { + STBTT_assert(pixels[i*stride_in_bytes] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + + pixels += 1; + } +} + +static float stbtt__oversample_shift(int oversample) +{ + if (!oversample) + return 0.0f; + + // The prefilter is a box filter of width "oversample", + // which shifts phase by (oversample - 1)/2 pixels in + // oversampled space. We want to shift in the opposite + // direction to counter this. + return (float)-(oversample - 1) / (2.0f * (float)oversample); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k; + int missing_glyph_added = 0; + + k=0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + ranges[i].h_oversample = (unsigned char) spc->h_oversample; + ranges[i].v_oversample = (unsigned char) spc->v_oversample; + for (j=0; j < ranges[i].num_chars; ++j) { + int x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { + rects[k].w = rects[k].h = 0; + } else { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; + } + ++k; + } + } + + return k; +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k, missing_glyph = -1, return_value = 1; + + // save current values + int old_h_over = spc->h_oversample; + int old_v_over = spc->v_oversample; + + k = 0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float recip_h,recip_v,sub_x,sub_y; + spc->h_oversample = ranges[i].h_oversample; + spc->v_oversample = ranges[i].v_oversample; + recip_h = 1.0f / spc->h_oversample; + recip_v = 1.0f / spc->v_oversample; + sub_x = stbtt__oversample_shift(spc->h_oversample); + sub_y = stbtt__oversample_shift(spc->v_oversample); + for (j=0; j < ranges[i].num_chars; ++j) { + stbrp_rect *r = &rects[k]; + if (r->was_packed && r->w != 0 && r->h != 0) { + stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; + int advance, lsb, x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbrp_coord pad = (stbrp_coord) spc->padding; + + // pad on left and top + r->x += pad; + r->y += pad; + r->w -= pad; + r->h -= pad; + stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(info, glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + &x0,&y0,&x1,&y1); + stbtt_MakeGlyphBitmapSubpixel(info, + spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w - spc->h_oversample+1, + r->h - spc->v_oversample+1, + spc->stride_in_bytes, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + glyph); + + if (spc->h_oversample > 1) + stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->h_oversample); + + if (spc->v_oversample > 1) + stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->v_oversample); + + bc->x0 = (stbtt_int16) r->x; + bc->y0 = (stbtt_int16) r->y; + bc->x1 = (stbtt_int16) (r->x + r->w); + bc->y1 = (stbtt_int16) (r->y + r->h); + bc->xadvance = scale * advance; + bc->xoff = (float) x0 * recip_h + sub_x; + bc->yoff = (float) y0 * recip_v + sub_y; + bc->xoff2 = (x0 + r->w) * recip_h + sub_x; + bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; + } else { + return_value = 0; // if any fail, report failure + } + + ++k; + } + } + + // restore original values + spc->h_oversample = old_h_over; + spc->v_oversample = old_v_over; + + return return_value; +} + +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) +{ + stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); +} + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +{ + stbtt_fontinfo info; + int i,j,n, return_value = 1; + //stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; + + // flag all characters as NOT packed + for (i=0; i < num_ranges; ++i) + for (j=0; j < ranges[i].num_chars; ++j) + ranges[i].chardata_for_range[j].x0 = + ranges[i].chardata_for_range[j].y0 = + ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; + + n = 0; + for (i=0; i < num_ranges; ++i) + n += ranges[i].num_chars; + + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) + return 0; + + info.userdata = spc->user_allocator_context; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + + n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); + + stbtt_PackFontRangesPackRects(spc, rects, n); + + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + + STBTT_free(rects, spc->user_allocator_context); + return return_value; +} + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) +{ + stbtt_pack_range range; + range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; + range.array_of_unicode_codepoints = NULL; + range.num_chars = num_chars_in_range; + range.chardata_for_range = chardata_for_range; + range.font_size = font_size; + return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); +} + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) +{ + int i_ascent, i_descent, i_lineGap; + float scale; + stbtt_fontinfo info; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); + scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); + *ascent = (float) i_ascent * scale; + *descent = (float) i_descent * scale; + *lineGap = (float) i_lineGap * scale; +} + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +{ + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_packedchar *b = chardata + char_index; + + if (align_to_integer) { + float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); + float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); + q->x0 = x; + q->y0 = y; + q->x1 = x + b->xoff2 - b->xoff; + q->y1 = y + b->yoff2 - b->yoff; + } else { + q->x0 = *xpos + b->xoff; + q->y0 = *ypos + b->yoff; + q->x1 = *xpos + b->xoff2; + q->y1 = *ypos + b->yoff2; + } + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + + orig[0] = x; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + a*x^2 + b*x + c = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + if (scale == 0) return NULL; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 != 0.0f) + precompute[i] = 1.0f / (bx*bx + by*by); + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3] = {0.f,0.f,0.f}; + float px,py,t,it,dist2; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (a == 0.0) { // if a is 0, it's linear + if (b != 0.0) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// font name matching -- recommended not to use this +// + +// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +{ + stbtt_int32 i=0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) { + stbtt_uint16 ch = s2[0]*256 + s2[1]; + if (ch < 0x80) { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } else if (ch < 0x800) { + if (i+1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } else if (ch >= 0xd800 && ch < 0xdc00) { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2]*256 + s2[3]; + if (i+3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } else if (ch >= 0xdc00 && ch < 0xe000) { + return -1; + } else { + if (i+2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; +} + +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +{ + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); +} + +// returns results in whatever encoding you request... but note that 2-byte encodings +// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +{ + stbtt_int32 i,count,stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc+nm+2); + stringOffset = nm + ttUSHORT(fc+nm+4); + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) + && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { + *length = ttUSHORT(fc+loc+8); + return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc+nm+2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); + + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc+loc+6); + if (id == target_id) { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { + stbtt_int32 slen = ttUSHORT(fc+loc+8); + stbtt_int32 off = ttUSHORT(fc+loc+10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); + if (matchlen >= 0) { + // check for target_id+1 immediately following, with same encoding & language + if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { + slen = ttUSHORT(fc+loc+12+8); + off = ttUSHORT(fc+loc+12+10); + if (slen == 0) { + if (matchlen == nlen) + return 1; + } else if (matchlen < nlen && name[matchlen] == ' ') { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + return 1; + } + } else { + // if nothing immediately following + if (matchlen == nlen) + return 1; + } + } + } + + // @TODO handle other encodings + } + } + return 0; +} + +static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) +{ + stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); + stbtt_uint32 nm,hd; + if (!stbtt__isfont(fc+offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) { + hd = stbtt__find_table(fc, offset, "head"); + if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return 0; + + if (flags) { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } else { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; +} + +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) +{ + stbtt_int32 i; + for (i=0;;++i) { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0) return off; + if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) + return off; + } +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, offset); +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // STB_TRUETYPE_IMPLEMENTATION + + +// FULL VERSION HISTORY +// +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// allow PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) +// also more precise AA rasterizer, except if shapes overlap +// remove need for STBTT_sort +// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC +// 1.04 (2015-04-15) typo in example +// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes +// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ +// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match +// non-oversampled; STBTT_POINT_SIZE for packed case only +// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling +// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) +// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID +// 0.8b (2014-07-07) fix a warning +// 0.8 (2014-05-25) fix a few more warnings +// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back +// 0.6c (2012-07-24) improve documentation +// 0.6b (2012-07-20) fix a few more warnings +// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, +// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty +// 0.5 (2011-12-09) bugfixes: +// subpixel glyph renderer computed wrong bounding box +// first vertex of shape can be off-curve (FreeSans) +// 0.4b (2011-12-03) fixed an error in the font baking example +// 0.4 (2011-12-01) kerning, subpixel rendering (tor) +// bugfixes for: +// codepoint-to-glyph conversion using table fmt=12 +// codepoint-to-glyph conversion using table fmt=4 +// stbtt_GetBakedQuad with non-square texture (Zer) +// updated Hello World! sample to use kerning and subpixel +// fixed some warnings +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (stb) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/resources/stb_vorbis.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/resources/stb_vorbis.c Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,5584 @@ +// Ogg Vorbis audio decoder - v1.22 - public domain +// http://nothings.org/stb_vorbis/ +// +// Original version written by Sean Barrett in 2007. +// +// Originally sponsored by RAD Game Tools. Seeking implementation +// sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker, +// Elias Software, Aras Pranckevicius, and Sean Barrett. +// +// LICENSE +// +// See end of file for license information. +// +// Limitations: +// +// - floor 0 not supported (used in old ogg vorbis files pre-2004) +// - lossless sample-truncation at beginning ignored +// - cannot concatenate multiple vorbis streams +// - sample positions are 32-bit, limiting seekable 192Khz +// files to around 6 hours (Ogg supports 64-bit) +// +// Feature contributors: +// Dougall Johnson (sample-exact seeking) +// +// Bugfix/warning contributors: +// Terje Mathisen Niklas Frykholm Andy Hill +// Casey Muratori John Bolton Gargaj +// Laurent Gomila Marc LeBlanc Ronny Chevalier +// Bernhard Wodo Evan Balster github:alxprd +// Tom Beaumont Ingo Leitgeb Nicolas Guillemot +// Phillip Bennefall Rohit Thiago Goulart +// github:manxorist Saga Musix github:infatum +// Timur Gagiev Maxwell Koo Peter Waller +// github:audinowho Dougall Johnson David Reid +// github:Clownacy Pedro J. Estebanez Remi Verschelde +// AnthoFoxo github:morlat Gabriel Ravier +// +// Partial history: +// 1.22 - 2021-07-11 - various small fixes +// 1.21 - 2021-07-02 - fix bug for files with no comments +// 1.20 - 2020-07-11 - several small fixes +// 1.19 - 2020-02-05 - warnings +// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc. +// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure) +// 1.16 - 2019-03-04 - fix warnings +// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found +// 1.14 - 2018-02-11 - delete bogus dealloca usage +// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully) +// 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files +// 1.11 - 2017-07-23 - fix MinGW compilation +// 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory +// 1.09 - 2016-04-04 - back out 'truncation of last frame' fix from previous version +// 1.08 - 2016-04-02 - warnings; setup memory leaks; truncation of last frame +// 1.07 - 2015-01-16 - fixes for crashes on invalid files; warning fixes; const +// 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson) +// some crash fixes when out of memory or with corrupt files +// fix some inappropriately signed shifts +// 1.05 - 2015-04-19 - don't define __forceinline if it's redundant +// 1.04 - 2014-08-27 - fix missing const-correct case in API +// 1.03 - 2014-08-07 - warning fixes +// 1.02 - 2014-07-09 - declare qsort comparison as explicitly _cdecl in Windows +// 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float (interleaved was correct) +// 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in >2-channel; +// (API change) report sample rate for decode-full-file funcs +// +// See end of file for full version history. + + +////////////////////////////////////////////////////////////////////////////// +// +// HEADER BEGINS HERE +// + +#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H +#define STB_VORBIS_INCLUDE_STB_VORBIS_H + +#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) +#define STB_VORBIS_NO_STDIO 1 +#endif + +#ifndef STB_VORBIS_NO_STDIO +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/////////// THREAD SAFETY + +// Individual stb_vorbis* handles are not thread-safe; you cannot decode from +// them from multiple threads at the same time. However, you can have multiple +// stb_vorbis* handles and decode from them independently in multiple thrads. + + +/////////// MEMORY ALLOCATION + +// normally stb_vorbis uses malloc() to allocate memory at startup, +// and alloca() to allocate temporary memory during a frame on the +// stack. (Memory consumption will depend on the amount of setup +// data in the file and how you set the compile flags for speed +// vs. size. In my test files the maximal-size usage is ~150KB.) +// +// You can modify the wrapper functions in the source (setup_malloc, +// setup_temp_malloc, temp_malloc) to change this behavior, or you +// can use a simpler allocation model: you pass in a buffer from +// which stb_vorbis will allocate _all_ its memory (including the +// temp memory). "open" may fail with a VORBIS_outofmem if you +// do not pass in enough data; there is no way to determine how +// much you do need except to succeed (at which point you can +// query get_info to find the exact amount required. yes I know +// this is lame). +// +// If you pass in a non-NULL buffer of the type below, allocation +// will occur from it as described above. Otherwise just pass NULL +// to use malloc()/alloca() + +typedef struct +{ + char *alloc_buffer; + int alloc_buffer_length_in_bytes; +} stb_vorbis_alloc; + + +/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES + +typedef struct stb_vorbis stb_vorbis; + +typedef struct +{ + unsigned int sample_rate; + int channels; + + unsigned int setup_memory_required; + unsigned int setup_temp_memory_required; + unsigned int temp_memory_required; + + int max_frame_size; +} stb_vorbis_info; + +typedef struct +{ + char *vendor; + + int comment_list_length; + char **comment_list; +} stb_vorbis_comment; + +// get general information about the file +extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f); + +// get ogg comments +extern stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f); + +// get the last error detected (clears it, too) +extern int stb_vorbis_get_error(stb_vorbis *f); + +// close an ogg vorbis file and free all memory in use +extern void stb_vorbis_close(stb_vorbis *f); + +// this function returns the offset (in samples) from the beginning of the +// file that will be returned by the next decode, if it is known, or -1 +// otherwise. after a flush_pushdata() call, this may take a while before +// it becomes valid again. +// NOT WORKING YET after a seek with PULLDATA API +extern int stb_vorbis_get_sample_offset(stb_vorbis *f); + +// returns the current seek point within the file, or offset from the beginning +// of the memory buffer. In pushdata mode it returns 0. +extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f); + +/////////// PUSHDATA API + +#ifndef STB_VORBIS_NO_PUSHDATA_API + +// this API allows you to get blocks of data from any source and hand +// them to stb_vorbis. you have to buffer them; stb_vorbis will tell +// you how much it used, and you have to give it the rest next time; +// and stb_vorbis may not have enough data to work with and you will +// need to give it the same data again PLUS more. Note that the Vorbis +// specification does not bound the size of an individual frame. + +extern stb_vorbis *stb_vorbis_open_pushdata( + const unsigned char * datablock, int datablock_length_in_bytes, + int *datablock_memory_consumed_in_bytes, + int *error, + const stb_vorbis_alloc *alloc_buffer); +// create a vorbis decoder by passing in the initial data block containing +// the ogg&vorbis headers (you don't need to do parse them, just provide +// the first N bytes of the file--you're told if it's not enough, see below) +// on success, returns an stb_vorbis *, does not set error, returns the amount of +// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes; +// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed +// if returns NULL and *error is VORBIS_need_more_data, then the input block was +// incomplete and you need to pass in a larger block from the start of the file + +extern int stb_vorbis_decode_frame_pushdata( + stb_vorbis *f, + const unsigned char *datablock, int datablock_length_in_bytes, + int *channels, // place to write number of float * buffers + float ***output, // place to write float ** array of float * buffers + int *samples // place to write number of output samples + ); +// decode a frame of audio sample data if possible from the passed-in data block +// +// return value: number of bytes we used from datablock +// +// possible cases: +// 0 bytes used, 0 samples output (need more data) +// N bytes used, 0 samples output (resynching the stream, keep going) +// N bytes used, M samples output (one frame of data) +// note that after opening a file, you will ALWAYS get one N-bytes,0-sample +// frame, because Vorbis always "discards" the first frame. +// +// Note that on resynch, stb_vorbis will rarely consume all of the buffer, +// instead only datablock_length_in_bytes-3 or less. This is because it wants +// to avoid missing parts of a page header if they cross a datablock boundary, +// without writing state-machiney code to record a partial detection. +// +// The number of channels returned are stored in *channels (which can be +// NULL--it is always the same as the number of channels reported by +// get_info). *output will contain an array of float* buffers, one per +// channel. In other words, (*output)[0][0] contains the first sample from +// the first channel, and (*output)[1][0] contains the first sample from +// the second channel. +// +// *output points into stb_vorbis's internal output buffer storage; these +// buffers are owned by stb_vorbis and application code should not free +// them or modify their contents. They are transient and will be overwritten +// once you ask for more data to get decoded, so be sure to grab any data +// you need before then. + +extern void stb_vorbis_flush_pushdata(stb_vorbis *f); +// inform stb_vorbis that your next datablock will not be contiguous with +// previous ones (e.g. you've seeked in the data); future attempts to decode +// frames will cause stb_vorbis to resynchronize (as noted above), and +// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it +// will begin decoding the _next_ frame. +// +// if you want to seek using pushdata, you need to seek in your file, then +// call stb_vorbis_flush_pushdata(), then start calling decoding, then once +// decoding is returning you data, call stb_vorbis_get_sample_offset, and +// if you don't like the result, seek your file again and repeat. +#endif + + +////////// PULLING INPUT API + +#ifndef STB_VORBIS_NO_PULLDATA_API +// This API assumes stb_vorbis is allowed to pull data from a source-- +// either a block of memory containing the _entire_ vorbis stream, or a +// FILE * that you or it create, or possibly some other reading mechanism +// if you go modify the source to replace the FILE * case with some kind +// of callback to your code. (But if you don't support seeking, you may +// just want to go ahead and use pushdata.) + +#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION) +extern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output); +#endif +#if !defined(STB_VORBIS_NO_INTEGER_CONVERSION) +extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output); +#endif +// decode an entire file and output the data interleaved into a malloc()ed +// buffer stored in *output. The return value is the number of samples +// decoded, or -1 if the file could not be opened or was not an ogg vorbis file. +// When you're done with it, just free() the pointer returned in *output. + +extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, + int *error, const stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from an ogg vorbis stream in memory (note +// this must be the entire stream!). on failure, returns NULL and sets *error + +#ifndef STB_VORBIS_NO_STDIO +extern stb_vorbis * stb_vorbis_open_filename(const char *filename, + int *error, const stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from a filename via fopen(). on failure, +// returns NULL and sets *error (possibly to VORBIS_file_open_failure). + +extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, + int *error, const stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from an open FILE *, looking for a stream at +// the _current_ seek point (ftell). on failure, returns NULL and sets *error. +// note that stb_vorbis must "own" this stream; if you seek it in between +// calls to stb_vorbis, it will become confused. Moreover, if you attempt to +// perform stb_vorbis_seek_*() operations on this file, it will assume it +// owns the _entire_ rest of the file after the start point. Use the next +// function, stb_vorbis_open_file_section(), to limit it. + +extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close, + int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len); +// create an ogg vorbis decoder from an open FILE *, looking for a stream at +// the _current_ seek point (ftell); the stream will be of length 'len' bytes. +// on failure, returns NULL and sets *error. note that stb_vorbis must "own" +// this stream; if you seek it in between calls to stb_vorbis, it will become +// confused. +#endif + +extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number); +extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); +// these functions seek in the Vorbis file to (approximately) 'sample_number'. +// after calling seek_frame(), the next call to get_frame_*() will include +// the specified sample. after calling stb_vorbis_seek(), the next call to +// stb_vorbis_get_samples_* will start with the specified sample. If you +// do not need to seek to EXACTLY the target sample when using get_samples_*, +// you can also use seek_frame(). + +extern int stb_vorbis_seek_start(stb_vorbis *f); +// this function is equivalent to stb_vorbis_seek(f,0) + +extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f); +extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f); +// these functions return the total length of the vorbis stream + +extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output); +// decode the next frame and return the number of samples. the number of +// channels returned are stored in *channels (which can be NULL--it is always +// the same as the number of channels reported by get_info). *output will +// contain an array of float* buffers, one per channel. These outputs will +// be overwritten on the next call to stb_vorbis_get_frame_*. +// +// You generally should not intermix calls to stb_vorbis_get_frame_*() +// and stb_vorbis_get_samples_*(), since the latter calls the former. + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts); +extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples); +#endif +// decode the next frame and return the number of *samples* per channel. +// Note that for interleaved data, you pass in the number of shorts (the +// size of your array), but the return value is the number of samples per +// channel, not the total number of samples. +// +// The data is coerced to the number of channels you request according to the +// channel coercion rules (see below). You must pass in the size of your +// buffer(s) so that stb_vorbis will not overwrite the end of the buffer. +// The maximum buffer size needed can be gotten from get_info(); however, +// the Vorbis I specification implies an absolute maximum of 4096 samples +// per channel. + +// Channel coercion rules: +// Let M be the number of channels requested, and N the number of channels present, +// and Cn be the nth channel; let stereo L be the sum of all L and center channels, +// and stereo R be the sum of all R and center channels (channel assignment from the +// vorbis spec). +// M N output +// 1 k sum(Ck) for all k +// 2 * stereo L, stereo R +// k l k > l, the first l channels, then 0s +// k l k <= l, the first k channels +// Note that this is not _good_ surround etc. mixing at all! It's just so +// you get something useful. + +extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats); +extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples); +// gets num_samples samples, not necessarily on a frame boundary--this requires +// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES. +// Returns the number of samples stored per channel; it may be less than requested +// at the end of the file. If there are no more samples in the file, returns 0. + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts); +extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples); +#endif +// gets num_samples samples, not necessarily on a frame boundary--this requires +// buffering so you have to supply the buffers. Applies the coercion rules above +// to produce 'channels' channels. Returns the number of samples stored per channel; +// it may be less than requested at the end of the file. If there are no more +// samples in the file, returns 0. + +#endif + +//////// ERROR CODES + +enum STBVorbisError +{ + VORBIS__no_error, + + VORBIS_need_more_data=1, // not a real error + + VORBIS_invalid_api_mixing, // can't mix API modes + VORBIS_outofmem, // not enough memory + VORBIS_feature_not_supported, // uses floor 0 + VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small + VORBIS_file_open_failure, // fopen() failed + VORBIS_seek_without_length, // can't seek in unknown-length file + + VORBIS_unexpected_eof=10, // file is truncated? + VORBIS_seek_invalid, // seek past EOF + + // decoding errors (corrupt/invalid stream) -- you probably + // don't care about the exact details of these + + // vorbis errors: + VORBIS_invalid_setup=20, + VORBIS_invalid_stream, + + // ogg errors: + VORBIS_missing_capture_pattern=30, + VORBIS_invalid_stream_structure_version, + VORBIS_continued_packet_flag_invalid, + VORBIS_incorrect_stream_serial_number, + VORBIS_invalid_first_page, + VORBIS_bad_packet_type, + VORBIS_cant_find_last_page, + VORBIS_seek_failed, + VORBIS_ogg_skeleton_not_supported +}; + + +#ifdef __cplusplus +} +#endif + +#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H +// +// HEADER ENDS HERE +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef STB_VORBIS_HEADER_ONLY + +// global configuration settings (e.g. set these in the project/makefile), +// or just set them in this file at the top (although ideally the first few +// should be visible when the header file is compiled too, although it's not +// crucial) + +// STB_VORBIS_NO_PUSHDATA_API +// does not compile the code for the various stb_vorbis_*_pushdata() +// functions +// #define STB_VORBIS_NO_PUSHDATA_API + +// STB_VORBIS_NO_PULLDATA_API +// does not compile the code for the non-pushdata APIs +// #define STB_VORBIS_NO_PULLDATA_API + +// STB_VORBIS_NO_STDIO +// does not compile the code for the APIs that use FILE *s internally +// or externally (implied by STB_VORBIS_NO_PULLDATA_API) +// #define STB_VORBIS_NO_STDIO + +// STB_VORBIS_NO_INTEGER_CONVERSION +// does not compile the code for converting audio sample data from +// float to integer (implied by STB_VORBIS_NO_PULLDATA_API) +// #define STB_VORBIS_NO_INTEGER_CONVERSION + +// STB_VORBIS_NO_FAST_SCALED_FLOAT +// does not use a fast float-to-int trick to accelerate float-to-int on +// most platforms which requires endianness be defined correctly. +//#define STB_VORBIS_NO_FAST_SCALED_FLOAT + + +// STB_VORBIS_MAX_CHANNELS [number] +// globally define this to the maximum number of channels you need. +// The spec does not put a restriction on channels except that +// the count is stored in a byte, so 255 is the hard limit. +// Reducing this saves about 16 bytes per value, so using 16 saves +// (255-16)*16 or around 4KB. Plus anything other memory usage +// I forgot to account for. Can probably go as low as 8 (7.1 audio), +// 6 (5.1 audio), or 2 (stereo only). +#ifndef STB_VORBIS_MAX_CHANNELS +#define STB_VORBIS_MAX_CHANNELS 16 // enough for anyone? +#endif + +// STB_VORBIS_PUSHDATA_CRC_COUNT [number] +// after a flush_pushdata(), stb_vorbis begins scanning for the +// next valid page, without backtracking. when it finds something +// that looks like a page, it streams through it and verifies its +// CRC32. Should that validation fail, it keeps scanning. But it's +// possible that _while_ streaming through to check the CRC32 of +// one candidate page, it sees another candidate page. This #define +// determines how many "overlapping" candidate pages it can search +// at once. Note that "real" pages are typically ~4KB to ~8KB, whereas +// garbage pages could be as big as 64KB, but probably average ~16KB. +// So don't hose ourselves by scanning an apparent 64KB page and +// missing a ton of real ones in the interim; so minimum of 2 +#ifndef STB_VORBIS_PUSHDATA_CRC_COUNT +#define STB_VORBIS_PUSHDATA_CRC_COUNT 4 +#endif + +// STB_VORBIS_FAST_HUFFMAN_LENGTH [number] +// sets the log size of the huffman-acceleration table. Maximum +// supported value is 24. with larger numbers, more decodings are O(1), +// but the table size is larger so worse cache missing, so you'll have +// to probe (and try multiple ogg vorbis files) to find the sweet spot. +#ifndef STB_VORBIS_FAST_HUFFMAN_LENGTH +#define STB_VORBIS_FAST_HUFFMAN_LENGTH 10 +#endif + +// STB_VORBIS_FAST_BINARY_LENGTH [number] +// sets the log size of the binary-search acceleration table. this +// is used in similar fashion to the fast-huffman size to set initial +// parameters for the binary search + +// STB_VORBIS_FAST_HUFFMAN_INT +// The fast huffman tables are much more efficient if they can be +// stored as 16-bit results instead of 32-bit results. This restricts +// the codebooks to having only 65535 possible outcomes, though. +// (At least, accelerated by the huffman table.) +#ifndef STB_VORBIS_FAST_HUFFMAN_INT +#define STB_VORBIS_FAST_HUFFMAN_SHORT +#endif + +// STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH +// If the 'fast huffman' search doesn't succeed, then stb_vorbis falls +// back on binary searching for the correct one. This requires storing +// extra tables with the huffman codes in sorted order. Defining this +// symbol trades off space for speed by forcing a linear search in the +// non-fast case, except for "sparse" codebooks. +// #define STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH + +// STB_VORBIS_DIVIDES_IN_RESIDUE +// stb_vorbis precomputes the result of the scalar residue decoding +// that would otherwise require a divide per chunk. you can trade off +// space for time by defining this symbol. +// #define STB_VORBIS_DIVIDES_IN_RESIDUE + +// STB_VORBIS_DIVIDES_IN_CODEBOOK +// vorbis VQ codebooks can be encoded two ways: with every case explicitly +// stored, or with all elements being chosen from a small range of values, +// and all values possible in all elements. By default, stb_vorbis expands +// this latter kind out to look like the former kind for ease of decoding, +// because otherwise an integer divide-per-vector-element is required to +// unpack the index. If you define STB_VORBIS_DIVIDES_IN_CODEBOOK, you can +// trade off storage for speed. +//#define STB_VORBIS_DIVIDES_IN_CODEBOOK + +#ifdef STB_VORBIS_CODEBOOK_SHORTS +#error "STB_VORBIS_CODEBOOK_SHORTS is no longer supported as it produced incorrect results for some input formats" +#endif + +// STB_VORBIS_DIVIDE_TABLE +// this replaces small integer divides in the floor decode loop with +// table lookups. made less than 1% difference, so disabled by default. + +// STB_VORBIS_NO_INLINE_DECODE +// disables the inlining of the scalar codebook fast-huffman decode. +// might save a little codespace; useful for debugging +// #define STB_VORBIS_NO_INLINE_DECODE + +// STB_VORBIS_NO_DEFER_FLOOR +// Normally we only decode the floor without synthesizing the actual +// full curve. We can instead synthesize the curve immediately. This +// requires more memory and is very likely slower, so I don't think +// you'd ever want to do it except for debugging. +// #define STB_VORBIS_NO_DEFER_FLOOR + + + + +////////////////////////////////////////////////////////////////////////////// + +#ifdef STB_VORBIS_NO_PULLDATA_API + #define STB_VORBIS_NO_INTEGER_CONVERSION + #define STB_VORBIS_NO_STDIO +#endif + +#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) + #define STB_VORBIS_NO_STDIO 1 +#endif + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT + + // only need endianness for fast-float-to-int, which we don't + // use for pushdata + + #ifndef STB_VORBIS_BIG_ENDIAN + #define STB_VORBIS_ENDIAN 0 + #else + #define STB_VORBIS_ENDIAN 1 + #endif + +#endif +#endif + + +#ifndef STB_VORBIS_NO_STDIO +#include +#endif + +#ifndef STB_VORBIS_NO_CRT + #include + #include + #include + #include + + // find definition of alloca if it's not in stdlib.h: + #if defined(_MSC_VER) || defined(__MINGW32__) + #include + #endif + #if defined(__linux__) || defined(__linux) || defined(__sun__) || defined(__EMSCRIPTEN__) || defined(__NEWLIB__) + #include + #endif +#else // STB_VORBIS_NO_CRT + #define NULL 0 + #define malloc(s) 0 + #define free(s) ((void) 0) + #define realloc(s) 0 +#endif // STB_VORBIS_NO_CRT + +#include + +#ifdef __MINGW32__ + // eff you mingw: + // "fixed": + // http://sourceforge.net/p/mingw-w64/mailman/message/32882927/ + // "no that broke the build, reverted, who cares about C": + // http://sourceforge.net/p/mingw-w64/mailman/message/32890381/ + #ifdef __forceinline + #undef __forceinline + #endif + #define __forceinline + #ifndef alloca + #define alloca __builtin_alloca + #endif +#elif !defined(_MSC_VER) + #if __GNUC__ + #define __forceinline inline + #else + #define __forceinline + #endif +#endif + +#if STB_VORBIS_MAX_CHANNELS > 256 +#error "Value of STB_VORBIS_MAX_CHANNELS outside of allowed range" +#endif + +#if STB_VORBIS_FAST_HUFFMAN_LENGTH > 24 +#error "Value of STB_VORBIS_FAST_HUFFMAN_LENGTH outside of allowed range" +#endif + + +#if 0 +#include +#define CHECK(f) _CrtIsValidHeapPointer(f->channel_buffers[1]) +#else +#define CHECK(f) ((void) 0) +#endif + +#define MAX_BLOCKSIZE_LOG 13 // from specification +#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG) + + +typedef unsigned char uint8; +typedef signed char int8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +typedef float codetype; + +#ifdef _MSC_VER +#define STBV_NOTUSED(v) (void)(v) +#else +#define STBV_NOTUSED(v) (void)sizeof(v) +#endif + +// @NOTE +// +// Some arrays below are tagged "//varies", which means it's actually +// a variable-sized piece of data, but rather than malloc I assume it's +// small enough it's better to just allocate it all together with the +// main thing +// +// Most of the variables are specified with the smallest size I could pack +// them into. It might give better performance to make them all full-sized +// integers. It should be safe to freely rearrange the structures or change +// the sizes larger--nothing relies on silently truncating etc., nor the +// order of variables. + +#define FAST_HUFFMAN_TABLE_SIZE (1 << STB_VORBIS_FAST_HUFFMAN_LENGTH) +#define FAST_HUFFMAN_TABLE_MASK (FAST_HUFFMAN_TABLE_SIZE - 1) + +typedef struct +{ + int dimensions, entries; + uint8 *codeword_lengths; + float minimum_value; + float delta_value; + uint8 value_bits; + uint8 lookup_type; + uint8 sequence_p; + uint8 sparse; + uint32 lookup_values; + codetype *multiplicands; + uint32 *codewords; + #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT + int16 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; + #else + int32 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; + #endif + uint32 *sorted_codewords; + int *sorted_values; + int sorted_entries; +} Codebook; + +typedef struct +{ + uint8 order; + uint16 rate; + uint16 bark_map_size; + uint8 amplitude_bits; + uint8 amplitude_offset; + uint8 number_of_books; + uint8 book_list[16]; // varies +} Floor0; + +typedef struct +{ + uint8 partitions; + uint8 partition_class_list[32]; // varies + uint8 class_dimensions[16]; // varies + uint8 class_subclasses[16]; // varies + uint8 class_masterbooks[16]; // varies + int16 subclass_books[16][8]; // varies + uint16 Xlist[31*8+2]; // varies + uint8 sorted_order[31*8+2]; + uint8 neighbors[31*8+2][2]; + uint8 floor1_multiplier; + uint8 rangebits; + int values; +} Floor1; + +typedef union +{ + Floor0 floor0; + Floor1 floor1; +} Floor; + +typedef struct +{ + uint32 begin, end; + uint32 part_size; + uint8 classifications; + uint8 classbook; + uint8 **classdata; + int16 (*residue_books)[8]; +} Residue; + +typedef struct +{ + uint8 magnitude; + uint8 angle; + uint8 mux; +} MappingChannel; + +typedef struct +{ + uint16 coupling_steps; + MappingChannel *chan; + uint8 submaps; + uint8 submap_floor[15]; // varies + uint8 submap_residue[15]; // varies +} Mapping; + +typedef struct +{ + uint8 blockflag; + uint8 mapping; + uint16 windowtype; + uint16 transformtype; +} Mode; + +typedef struct +{ + uint32 goal_crc; // expected crc if match + int bytes_left; // bytes left in packet + uint32 crc_so_far; // running crc + int bytes_done; // bytes processed in _current_ chunk + uint32 sample_loc; // granule pos encoded in page +} CRCscan; + +typedef struct +{ + uint32 page_start, page_end; + uint32 last_decoded_sample; +} ProbedPage; + +struct stb_vorbis +{ + // user-accessible info + unsigned int sample_rate; + int channels; + + unsigned int setup_memory_required; + unsigned int temp_memory_required; + unsigned int setup_temp_memory_required; + + char *vendor; + int comment_list_length; + char **comment_list; + + // input config +#ifndef STB_VORBIS_NO_STDIO + FILE *f; + uint32 f_start; + int close_on_free; +#endif + + uint8 *stream; + uint8 *stream_start; + uint8 *stream_end; + + uint32 stream_len; + + uint8 push_mode; + + // the page to seek to when seeking to start, may be zero + uint32 first_audio_page_offset; + + // p_first is the page on which the first audio packet ends + // (but not necessarily the page on which it starts) + ProbedPage p_first, p_last; + + // memory management + stb_vorbis_alloc alloc; + int setup_offset; + int temp_offset; + + // run-time results + int eof; + enum STBVorbisError error; + + // user-useful data + + // header info + int blocksize[2]; + int blocksize_0, blocksize_1; + int codebook_count; + Codebook *codebooks; + int floor_count; + uint16 floor_types[64]; // varies + Floor *floor_config; + int residue_count; + uint16 residue_types[64]; // varies + Residue *residue_config; + int mapping_count; + Mapping *mapping; + int mode_count; + Mode mode_config[64]; // varies + + uint32 total_samples; + + // decode buffer + float *channel_buffers[STB_VORBIS_MAX_CHANNELS]; + float *outputs [STB_VORBIS_MAX_CHANNELS]; + + float *previous_window[STB_VORBIS_MAX_CHANNELS]; + int previous_length; + + #ifndef STB_VORBIS_NO_DEFER_FLOOR + int16 *finalY[STB_VORBIS_MAX_CHANNELS]; + #else + float *floor_buffers[STB_VORBIS_MAX_CHANNELS]; + #endif + + uint32 current_loc; // sample location of next frame to decode + int current_loc_valid; + + // per-blocksize precomputed data + + // twiddle factors + float *A[2],*B[2],*C[2]; + float *window[2]; + uint16 *bit_reverse[2]; + + // current page/packet/segment streaming info + uint32 serial; // stream serial number for verification + int last_page; + int segment_count; + uint8 segments[255]; + uint8 page_flag; + uint8 bytes_in_seg; + uint8 first_decode; + int next_seg; + int last_seg; // flag that we're on the last segment + int last_seg_which; // what was the segment number of the last seg? + uint32 acc; + int valid_bits; + int packet_bytes; + int end_seg_with_known_loc; + uint32 known_loc_for_packet; + int discard_samples_deferred; + uint32 samples_output; + + // push mode scanning + int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching +#ifndef STB_VORBIS_NO_PUSHDATA_API + CRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT]; +#endif + + // sample-access + int channel_buffer_start; + int channel_buffer_end; +}; + +#if defined(STB_VORBIS_NO_PUSHDATA_API) + #define IS_PUSH_MODE(f) FALSE +#elif defined(STB_VORBIS_NO_PULLDATA_API) + #define IS_PUSH_MODE(f) TRUE +#else + #define IS_PUSH_MODE(f) ((f)->push_mode) +#endif + +typedef struct stb_vorbis vorb; + +static int error(vorb *f, enum STBVorbisError e) +{ + f->error = e; + if (!f->eof && e != VORBIS_need_more_data) { + f->error=e; // breakpoint for debugging + } + return 0; +} + + +// these functions are used for allocating temporary memory +// while decoding. if you can afford the stack space, use +// alloca(); otherwise, provide a temp buffer and it will +// allocate out of those. + +#define array_size_required(count,size) (count*(sizeof(void *)+(size))) + +#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size)) +#define temp_free(f,p) (void)0 +#define temp_alloc_save(f) ((f)->temp_offset) +#define temp_alloc_restore(f,p) ((f)->temp_offset = (p)) + +#define temp_block_array(f,count,size) make_block_array(temp_alloc(f,array_size_required(count,size)), count, size) + +// given a sufficiently large block of memory, make an array of pointers to subblocks of it +static void *make_block_array(void *mem, int count, int size) +{ + int i; + void ** p = (void **) mem; + char *q = (char *) (p + count); + for (i=0; i < count; ++i) { + p[i] = q; + q += size; + } + return p; +} + +static void *setup_malloc(vorb *f, int sz) +{ + sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs. + f->setup_memory_required += sz; + if (f->alloc.alloc_buffer) { + void *p = (char *) f->alloc.alloc_buffer + f->setup_offset; + if (f->setup_offset + sz > f->temp_offset) return NULL; + f->setup_offset += sz; + return p; + } + return sz ? malloc(sz) : NULL; +} + +static void setup_free(vorb *f, void *p) +{ + if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack + free(p); +} + +static void *setup_temp_malloc(vorb *f, int sz) +{ + sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs. + if (f->alloc.alloc_buffer) { + if (f->temp_offset - sz < f->setup_offset) return NULL; + f->temp_offset -= sz; + return (char *) f->alloc.alloc_buffer + f->temp_offset; + } + return malloc(sz); +} + +static void setup_temp_free(vorb *f, void *p, int sz) +{ + if (f->alloc.alloc_buffer) { + f->temp_offset += (sz+7)&~7; + return; + } + free(p); +} + +#define CRC32_POLY 0x04c11db7 // from spec + +static uint32 crc_table[256]; +static void crc32_init(void) +{ + int i,j; + uint32 s; + for(i=0; i < 256; i++) { + for (s=(uint32) i << 24, j=0; j < 8; ++j) + s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0); + crc_table[i] = s; + } +} + +static __forceinline uint32 crc32_update(uint32 crc, uint8 byte) +{ + return (crc << 8) ^ crc_table[byte ^ (crc >> 24)]; +} + + +// used in setup, and for huffman that doesn't go fast path +static unsigned int bit_reverse(unsigned int n) +{ + n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1); + n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2); + n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4); + n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8); + return (n >> 16) | (n << 16); +} + +static float square(float x) +{ + return x*x; +} + +// this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3 +// as required by the specification. fast(?) implementation from stb.h +// @OPTIMIZE: called multiple times per-packet with "constants"; move to setup +static int ilog(int32 n) +{ + static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; + + if (n < 0) return 0; // signed n returns 0 + + // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29) + if (n < (1 << 14)) + if (n < (1 << 4)) return 0 + log2_4[n ]; + else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; + else return 10 + log2_4[n >> 10]; + else if (n < (1 << 24)) + if (n < (1 << 19)) return 15 + log2_4[n >> 15]; + else return 20 + log2_4[n >> 20]; + else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; + else return 30 + log2_4[n >> 30]; +} + +#ifndef M_PI + #define M_PI 3.14159265358979323846264f // from CRC +#endif + +// code length assigned to a value with no huffman encoding +#define NO_CODE 255 + +/////////////////////// LEAF SETUP FUNCTIONS ////////////////////////// +// +// these functions are only called at setup, and only a few times +// per file + +static float float32_unpack(uint32 x) +{ + // from the specification + uint32 mantissa = x & 0x1fffff; + uint32 sign = x & 0x80000000; + uint32 exp = (x & 0x7fe00000) >> 21; + double res = sign ? -(double)mantissa : (double)mantissa; + return (float) ldexp((float)res, (int)exp-788); +} + + +// zlib & jpeg huffman tables assume that the output symbols +// can either be arbitrarily arranged, or have monotonically +// increasing frequencies--they rely on the lengths being sorted; +// this makes for a very simple generation algorithm. +// vorbis allows a huffman table with non-sorted lengths. This +// requires a more sophisticated construction, since symbols in +// order do not map to huffman codes "in order". +static void add_entry(Codebook *c, uint32 huff_code, int symbol, int count, int len, uint32 *values) +{ + if (!c->sparse) { + c->codewords [symbol] = huff_code; + } else { + c->codewords [count] = huff_code; + c->codeword_lengths[count] = len; + values [count] = symbol; + } +} + +static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) +{ + int i,k,m=0; + uint32 available[32]; + + memset(available, 0, sizeof(available)); + // find the first entry + for (k=0; k < n; ++k) if (len[k] < NO_CODE) break; + if (k == n) { assert(c->sorted_entries == 0); return TRUE; } + assert(len[k] < 32); // no error return required, code reading lens checks this + // add to the list + add_entry(c, 0, k, m++, len[k], values); + // add all available leaves + for (i=1; i <= len[k]; ++i) + available[i] = 1U << (32-i); + // note that the above code treats the first case specially, + // but it's really the same as the following code, so they + // could probably be combined (except the initial code is 0, + // and I use 0 in available[] to mean 'empty') + for (i=k+1; i < n; ++i) { + uint32 res; + int z = len[i], y; + if (z == NO_CODE) continue; + assert(z < 32); // no error return required, code reading lens checks this + // find lowest available leaf (should always be earliest, + // which is what the specification calls for) + // note that this property, and the fact we can never have + // more than one free leaf at a given level, isn't totally + // trivial to prove, but it seems true and the assert never + // fires, so! + while (z > 0 && !available[z]) --z; + if (z == 0) { return FALSE; } + res = available[z]; + available[z] = 0; + add_entry(c, bit_reverse(res), i, m++, len[i], values); + // propagate availability up the tree + if (z != len[i]) { + for (y=len[i]; y > z; --y) { + assert(available[y] == 0); + available[y] = res + (1 << (32-y)); + } + } + } + return TRUE; +} + +// accelerated huffman table allows fast O(1) match of all symbols +// of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH +static void compute_accelerated_huffman(Codebook *c) +{ + int i, len; + for (i=0; i < FAST_HUFFMAN_TABLE_SIZE; ++i) + c->fast_huffman[i] = -1; + + len = c->sparse ? c->sorted_entries : c->entries; + #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT + if (len > 32767) len = 32767; // largest possible value we can encode! + #endif + for (i=0; i < len; ++i) { + if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) { + uint32 z = c->sparse ? bit_reverse(c->sorted_codewords[i]) : c->codewords[i]; + // set table entries for all bit combinations in the higher bits + while (z < FAST_HUFFMAN_TABLE_SIZE) { + c->fast_huffman[z] = i; + z += 1 << c->codeword_lengths[i]; + } + } + } +} + +#ifdef _MSC_VER +#define STBV_CDECL __cdecl +#else +#define STBV_CDECL +#endif + +static int STBV_CDECL uint32_compare(const void *p, const void *q) +{ + uint32 x = * (uint32 *) p; + uint32 y = * (uint32 *) q; + return x < y ? -1 : x > y; +} + +static int include_in_sort(Codebook *c, uint8 len) +{ + if (c->sparse) { assert(len != NO_CODE); return TRUE; } + if (len == NO_CODE) return FALSE; + if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE; + return FALSE; +} + +// if the fast table above doesn't work, we want to binary +// search them... need to reverse the bits +static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values) +{ + int i, len; + // build a list of all the entries + // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN. + // this is kind of a frivolous optimization--I don't see any performance improvement, + // but it's like 4 extra lines of code, so. + if (!c->sparse) { + int k = 0; + for (i=0; i < c->entries; ++i) + if (include_in_sort(c, lengths[i])) + c->sorted_codewords[k++] = bit_reverse(c->codewords[i]); + assert(k == c->sorted_entries); + } else { + for (i=0; i < c->sorted_entries; ++i) + c->sorted_codewords[i] = bit_reverse(c->codewords[i]); + } + + qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), uint32_compare); + c->sorted_codewords[c->sorted_entries] = 0xffffffff; + + len = c->sparse ? c->sorted_entries : c->entries; + // now we need to indicate how they correspond; we could either + // #1: sort a different data structure that says who they correspond to + // #2: for each sorted entry, search the original list to find who corresponds + // #3: for each original entry, find the sorted entry + // #1 requires extra storage, #2 is slow, #3 can use binary search! + for (i=0; i < len; ++i) { + int huff_len = c->sparse ? lengths[values[i]] : lengths[i]; + if (include_in_sort(c,huff_len)) { + uint32 code = bit_reverse(c->codewords[i]); + int x=0, n=c->sorted_entries; + while (n > 1) { + // invariant: sc[x] <= code < sc[x+n] + int m = x + (n >> 1); + if (c->sorted_codewords[m] <= code) { + x = m; + n -= (n>>1); + } else { + n >>= 1; + } + } + assert(c->sorted_codewords[x] == code); + if (c->sparse) { + c->sorted_values[x] = values[i]; + c->codeword_lengths[x] = huff_len; + } else { + c->sorted_values[x] = i; + } + } + } +} + +// only run while parsing the header (3 times) +static int vorbis_validate(uint8 *data) +{ + static uint8 vorbis[6] = { 'v', 'o', 'r', 'b', 'i', 's' }; + return memcmp(data, vorbis, 6) == 0; +} + +// called from setup only, once per code book +// (formula implied by specification) +static int lookup1_values(int entries, int dim) +{ + int r = (int) floor(exp((float) log((float) entries) / dim)); + if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning; + ++r; // floor() to avoid _ftol() when non-CRT + if (pow((float) r+1, dim) <= entries) + return -1; + if ((int) floor(pow((float) r, dim)) > entries) + return -1; + return r; +} + +// called twice per file +static void compute_twiddle_factors(int n, float *A, float *B, float *C) +{ + int n4 = n >> 2, n8 = n >> 3; + int k,k2; + + for (k=k2=0; k < n4; ++k,k2+=2) { + A[k2 ] = (float) cos(4*k*M_PI/n); + A[k2+1] = (float) -sin(4*k*M_PI/n); + B[k2 ] = (float) cos((k2+1)*M_PI/n/2) * 0.5f; + B[k2+1] = (float) sin((k2+1)*M_PI/n/2) * 0.5f; + } + for (k=k2=0; k < n8; ++k,k2+=2) { + C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); + C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); + } +} + +static void compute_window(int n, float *window) +{ + int n2 = n >> 1, i; + for (i=0; i < n2; ++i) + window[i] = (float) sin(0.5 * M_PI * square((float) sin((i - 0 + 0.5) / n2 * 0.5 * M_PI))); +} + +static void compute_bitreverse(int n, uint16 *rev) +{ + int ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + int i, n8 = n >> 3; + for (i=0; i < n8; ++i) + rev[i] = (bit_reverse(i) >> (32-ld+3)) << 2; +} + +static int init_blocksize(vorb *f, int b, int n) +{ + int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3; + f->A[b] = (float *) setup_malloc(f, sizeof(float) * n2); + f->B[b] = (float *) setup_malloc(f, sizeof(float) * n2); + f->C[b] = (float *) setup_malloc(f, sizeof(float) * n4); + if (!f->A[b] || !f->B[b] || !f->C[b]) return error(f, VORBIS_outofmem); + compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]); + f->window[b] = (float *) setup_malloc(f, sizeof(float) * n2); + if (!f->window[b]) return error(f, VORBIS_outofmem); + compute_window(n, f->window[b]); + f->bit_reverse[b] = (uint16 *) setup_malloc(f, sizeof(uint16) * n8); + if (!f->bit_reverse[b]) return error(f, VORBIS_outofmem); + compute_bitreverse(n, f->bit_reverse[b]); + return TRUE; +} + +static void neighbors(uint16 *x, int n, int *plow, int *phigh) +{ + int low = -1; + int high = 65536; + int i; + for (i=0; i < n; ++i) { + if (x[i] > low && x[i] < x[n]) { *plow = i; low = x[i]; } + if (x[i] < high && x[i] > x[n]) { *phigh = i; high = x[i]; } + } +} + +// this has been repurposed so y is now the original index instead of y +typedef struct +{ + uint16 x,id; +} stbv__floor_ordering; + +static int STBV_CDECL point_compare(const void *p, const void *q) +{ + stbv__floor_ordering *a = (stbv__floor_ordering *) p; + stbv__floor_ordering *b = (stbv__floor_ordering *) q; + return a->x < b->x ? -1 : a->x > b->x; +} + +// +/////////////////////// END LEAF SETUP FUNCTIONS ////////////////////////// + + +#if defined(STB_VORBIS_NO_STDIO) + #define USE_MEMORY(z) TRUE +#else + #define USE_MEMORY(z) ((z)->stream) +#endif + +static uint8 get8(vorb *z) +{ + if (USE_MEMORY(z)) { + if (z->stream >= z->stream_end) { z->eof = TRUE; return 0; } + return *z->stream++; + } + + #ifndef STB_VORBIS_NO_STDIO + { + int c = fgetc(z->f); + if (c == EOF) { z->eof = TRUE; return 0; } + return c; + } + #endif +} + +static uint32 get32(vorb *f) +{ + uint32 x; + x = get8(f); + x += get8(f) << 8; + x += get8(f) << 16; + x += (uint32) get8(f) << 24; + return x; +} + +static int getn(vorb *z, uint8 *data, int n) +{ + if (USE_MEMORY(z)) { + if (z->stream+n > z->stream_end) { z->eof = 1; return 0; } + memcpy(data, z->stream, n); + z->stream += n; + return 1; + } + + #ifndef STB_VORBIS_NO_STDIO + if (fread(data, n, 1, z->f) == 1) + return 1; + else { + z->eof = 1; + return 0; + } + #endif +} + +static void skip(vorb *z, int n) +{ + if (USE_MEMORY(z)) { + z->stream += n; + if (z->stream >= z->stream_end) z->eof = 1; + return; + } + #ifndef STB_VORBIS_NO_STDIO + { + long x = ftell(z->f); + fseek(z->f, x+n, SEEK_SET); + } + #endif +} + +static int set_file_offset(stb_vorbis *f, unsigned int loc) +{ + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (f->push_mode) return 0; + #endif + f->eof = 0; + if (USE_MEMORY(f)) { + if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) { + f->stream = f->stream_end; + f->eof = 1; + return 0; + } else { + f->stream = f->stream_start + loc; + return 1; + } + } + #ifndef STB_VORBIS_NO_STDIO + if (loc + f->f_start < loc || loc >= 0x80000000) { + loc = 0x7fffffff; + f->eof = 1; + } else { + loc += f->f_start; + } + if (!fseek(f->f, loc, SEEK_SET)) + return 1; + f->eof = 1; + fseek(f->f, f->f_start, SEEK_END); + return 0; + #endif +} + + +static uint8 ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 }; + +static int capture_pattern(vorb *f) +{ + if (0x4f != get8(f)) return FALSE; + if (0x67 != get8(f)) return FALSE; + if (0x67 != get8(f)) return FALSE; + if (0x53 != get8(f)) return FALSE; + return TRUE; +} + +#define PAGEFLAG_continued_packet 1 +#define PAGEFLAG_first_page 2 +#define PAGEFLAG_last_page 4 + +static int start_page_no_capturepattern(vorb *f) +{ + uint32 loc0,loc1,n; + if (f->first_decode && !IS_PUSH_MODE(f)) { + f->p_first.page_start = stb_vorbis_get_file_offset(f) - 4; + } + // stream structure version + if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version); + // header flag + f->page_flag = get8(f); + // absolute granule position + loc0 = get32(f); + loc1 = get32(f); + // @TODO: validate loc0,loc1 as valid positions? + // stream serial number -- vorbis doesn't interleave, so discard + get32(f); + //if (f->serial != get32(f)) return error(f, VORBIS_incorrect_stream_serial_number); + // page sequence number + n = get32(f); + f->last_page = n; + // CRC32 + get32(f); + // page_segments + f->segment_count = get8(f); + if (!getn(f, f->segments, f->segment_count)) + return error(f, VORBIS_unexpected_eof); + // assume we _don't_ know any the sample position of any segments + f->end_seg_with_known_loc = -2; + if (loc0 != ~0U || loc1 != ~0U) { + int i; + // determine which packet is the last one that will complete + for (i=f->segment_count-1; i >= 0; --i) + if (f->segments[i] < 255) + break; + // 'i' is now the index of the _last_ segment of a packet that ends + if (i >= 0) { + f->end_seg_with_known_loc = i; + f->known_loc_for_packet = loc0; + } + } + if (f->first_decode) { + int i,len; + len = 0; + for (i=0; i < f->segment_count; ++i) + len += f->segments[i]; + len += 27 + f->segment_count; + f->p_first.page_end = f->p_first.page_start + len; + f->p_first.last_decoded_sample = loc0; + } + f->next_seg = 0; + return TRUE; +} + +static int start_page(vorb *f) +{ + if (!capture_pattern(f)) return error(f, VORBIS_missing_capture_pattern); + return start_page_no_capturepattern(f); +} + +static int start_packet(vorb *f) +{ + while (f->next_seg == -1) { + if (!start_page(f)) return FALSE; + if (f->page_flag & PAGEFLAG_continued_packet) + return error(f, VORBIS_continued_packet_flag_invalid); + } + f->last_seg = FALSE; + f->valid_bits = 0; + f->packet_bytes = 0; + f->bytes_in_seg = 0; + // f->next_seg is now valid + return TRUE; +} + +static int maybe_start_packet(vorb *f) +{ + if (f->next_seg == -1) { + int x = get8(f); + if (f->eof) return FALSE; // EOF at page boundary is not an error! + if (0x4f != x ) return error(f, VORBIS_missing_capture_pattern); + if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (0x53 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (!start_page_no_capturepattern(f)) return FALSE; + if (f->page_flag & PAGEFLAG_continued_packet) { + // set up enough state that we can read this packet if we want, + // e.g. during recovery + f->last_seg = FALSE; + f->bytes_in_seg = 0; + return error(f, VORBIS_continued_packet_flag_invalid); + } + } + return start_packet(f); +} + +static int next_segment(vorb *f) +{ + int len; + if (f->last_seg) return 0; + if (f->next_seg == -1) { + f->last_seg_which = f->segment_count-1; // in case start_page fails + if (!start_page(f)) { f->last_seg = 1; return 0; } + if (!(f->page_flag & PAGEFLAG_continued_packet)) return error(f, VORBIS_continued_packet_flag_invalid); + } + len = f->segments[f->next_seg++]; + if (len < 255) { + f->last_seg = TRUE; + f->last_seg_which = f->next_seg-1; + } + if (f->next_seg >= f->segment_count) + f->next_seg = -1; + assert(f->bytes_in_seg == 0); + f->bytes_in_seg = len; + return len; +} + +#define EOP (-1) +#define INVALID_BITS (-1) + +static int get8_packet_raw(vorb *f) +{ + if (!f->bytes_in_seg) { // CLANG! + if (f->last_seg) return EOP; + else if (!next_segment(f)) return EOP; + } + assert(f->bytes_in_seg > 0); + --f->bytes_in_seg; + ++f->packet_bytes; + return get8(f); +} + +static int get8_packet(vorb *f) +{ + int x = get8_packet_raw(f); + f->valid_bits = 0; + return x; +} + +static int get32_packet(vorb *f) +{ + uint32 x; + x = get8_packet(f); + x += get8_packet(f) << 8; + x += get8_packet(f) << 16; + x += (uint32) get8_packet(f) << 24; + return x; +} + +static void flush_packet(vorb *f) +{ + while (get8_packet_raw(f) != EOP); +} + +// @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important +// as the huffman decoder? +static uint32 get_bits(vorb *f, int n) +{ + uint32 z; + + if (f->valid_bits < 0) return 0; + if (f->valid_bits < n) { + if (n > 24) { + // the accumulator technique below would not work correctly in this case + z = get_bits(f, 24); + z += get_bits(f, n-24) << 24; + return z; + } + if (f->valid_bits == 0) f->acc = 0; + while (f->valid_bits < n) { + int z = get8_packet_raw(f); + if (z == EOP) { + f->valid_bits = INVALID_BITS; + return 0; + } + f->acc += z << f->valid_bits; + f->valid_bits += 8; + } + } + + assert(f->valid_bits >= n); + z = f->acc & ((1 << n)-1); + f->acc >>= n; + f->valid_bits -= n; + return z; +} + +// @OPTIMIZE: primary accumulator for huffman +// expand the buffer to as many bits as possible without reading off end of packet +// it might be nice to allow f->valid_bits and f->acc to be stored in registers, +// e.g. cache them locally and decode locally +static __forceinline void prep_huffman(vorb *f) +{ + if (f->valid_bits <= 24) { + if (f->valid_bits == 0) f->acc = 0; + do { + int z; + if (f->last_seg && !f->bytes_in_seg) return; + z = get8_packet_raw(f); + if (z == EOP) return; + f->acc += (unsigned) z << f->valid_bits; + f->valid_bits += 8; + } while (f->valid_bits <= 24); + } +} + +enum +{ + VORBIS_packet_id = 1, + VORBIS_packet_comment = 3, + VORBIS_packet_setup = 5 +}; + +static int codebook_decode_scalar_raw(vorb *f, Codebook *c) +{ + int i; + prep_huffman(f); + + if (c->codewords == NULL && c->sorted_codewords == NULL) + return -1; + + // cases to use binary search: sorted_codewords && !c->codewords + // sorted_codewords && c->entries > 8 + if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) { + // binary search + uint32 code = bit_reverse(f->acc); + int x=0, n=c->sorted_entries, len; + + while (n > 1) { + // invariant: sc[x] <= code < sc[x+n] + int m = x + (n >> 1); + if (c->sorted_codewords[m] <= code) { + x = m; + n -= (n>>1); + } else { + n >>= 1; + } + } + // x is now the sorted index + if (!c->sparse) x = c->sorted_values[x]; + // x is now sorted index if sparse, or symbol otherwise + len = c->codeword_lengths[x]; + if (f->valid_bits >= len) { + f->acc >>= len; + f->valid_bits -= len; + return x; + } + + f->valid_bits = 0; + return -1; + } + + // if small, linear search + assert(!c->sparse); + for (i=0; i < c->entries; ++i) { + if (c->codeword_lengths[i] == NO_CODE) continue; + if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) { + if (f->valid_bits >= c->codeword_lengths[i]) { + f->acc >>= c->codeword_lengths[i]; + f->valid_bits -= c->codeword_lengths[i]; + return i; + } + f->valid_bits = 0; + return -1; + } + } + + error(f, VORBIS_invalid_stream); + f->valid_bits = 0; + return -1; +} + +#ifndef STB_VORBIS_NO_INLINE_DECODE + +#define DECODE_RAW(var, f,c) \ + if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) \ + prep_huffman(f); \ + var = f->acc & FAST_HUFFMAN_TABLE_MASK; \ + var = c->fast_huffman[var]; \ + if (var >= 0) { \ + int n = c->codeword_lengths[var]; \ + f->acc >>= n; \ + f->valid_bits -= n; \ + if (f->valid_bits < 0) { f->valid_bits = 0; var = -1; } \ + } else { \ + var = codebook_decode_scalar_raw(f,c); \ + } + +#else + +static int codebook_decode_scalar(vorb *f, Codebook *c) +{ + int i; + if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) + prep_huffman(f); + // fast huffman table lookup + i = f->acc & FAST_HUFFMAN_TABLE_MASK; + i = c->fast_huffman[i]; + if (i >= 0) { + f->acc >>= c->codeword_lengths[i]; + f->valid_bits -= c->codeword_lengths[i]; + if (f->valid_bits < 0) { f->valid_bits = 0; return -1; } + return i; + } + return codebook_decode_scalar_raw(f,c); +} + +#define DECODE_RAW(var,f,c) var = codebook_decode_scalar(f,c); + +#endif + +#define DECODE(var,f,c) \ + DECODE_RAW(var,f,c) \ + if (c->sparse) var = c->sorted_values[var]; + +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + #define DECODE_VQ(var,f,c) DECODE_RAW(var,f,c) +#else + #define DECODE_VQ(var,f,c) DECODE(var,f,c) +#endif + + + + + + +// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case +// where we avoid one addition +#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) +#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) +#define CODEBOOK_ELEMENT_BASE(c) (0) + +static int codebook_decode_start(vorb *f, Codebook *c) +{ + int z = -1; + + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) + error(f, VORBIS_invalid_stream); + else { + DECODE_VQ(z,f,c); + if (c->sparse) assert(z < c->sorted_entries); + if (z < 0) { // check for EOP + if (!f->bytes_in_seg) + if (f->last_seg) + return z; + error(f, VORBIS_invalid_stream); + } + } + return z; +} + +static int codebook_decode(vorb *f, Codebook *c, float *output, int len) +{ + int i,z = codebook_decode_start(f,c); + if (z < 0) return FALSE; + if (len > c->dimensions) len = c->dimensions; + +#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + float last = CODEBOOK_ELEMENT_BASE(c); + int div = 1; + for (i=0; i < len; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + output[i] += val; + if (c->sequence_p) last = val + c->minimum_value; + div *= c->lookup_values; + } + return TRUE; + } +#endif + + z *= c->dimensions; + if (c->sequence_p) { + float last = CODEBOOK_ELEMENT_BASE(c); + for (i=0; i < len; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + output[i] += val; + last = val + c->minimum_value; + } + } else { + float last = CODEBOOK_ELEMENT_BASE(c); + for (i=0; i < len; ++i) { + output[i] += CODEBOOK_ELEMENT_FAST(c,z+i) + last; + } + } + + return TRUE; +} + +static int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, int step) +{ + int i,z = codebook_decode_start(f,c); + float last = CODEBOOK_ELEMENT_BASE(c); + if (z < 0) return FALSE; + if (len > c->dimensions) len = c->dimensions; + +#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int div = 1; + for (i=0; i < len; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + output[i*step] += val; + if (c->sequence_p) last = val; + div *= c->lookup_values; + } + return TRUE; + } +#endif + + z *= c->dimensions; + for (i=0; i < len; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + output[i*step] += val; + if (c->sequence_p) last = val; + } + + return TRUE; +} + +static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode) +{ + int c_inter = *c_inter_p; + int p_inter = *p_inter_p; + int i,z, effective = c->dimensions; + + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); + + while (total_decode > 0) { + float last = CODEBOOK_ELEMENT_BASE(c); + DECODE_VQ(z,f,c); + #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + assert(!c->sparse || z < c->sorted_entries); + #endif + if (z < 0) { + if (!f->bytes_in_seg) + if (f->last_seg) return FALSE; + return error(f, VORBIS_invalid_stream); + } + + // if this will take us off the end of the buffers, stop short! + // we check by computing the length of the virtual interleaved + // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), + // and the length we'll be using (effective) + if (c_inter + p_inter*ch + effective > len * ch) { + effective = len*ch - (p_inter*ch - c_inter); + } + + #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int div = 1; + for (i=0; i < effective; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + if (c->sequence_p) last = val; + div *= c->lookup_values; + } + } else + #endif + { + z *= c->dimensions; + if (c->sequence_p) { + for (i=0; i < effective; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + last = val; + } + } else { + for (i=0; i < effective; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + } + } + } + + total_decode -= effective; + } + *c_inter_p = c_inter; + *p_inter_p = p_inter; + return TRUE; +} + +static int predict_point(int x, int x0, int x1, int y0, int y1) +{ + int dy = y1 - y0; + int adx = x1 - x0; + // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86? + int err = abs(dy) * (x - x0); + int off = err / adx; + return dy < 0 ? y0 - off : y0 + off; +} + +// the following table is block-copied from the specification +static float inverse_db_table[256] = +{ + 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, + 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, + 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, + 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, + 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, + 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, + 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, + 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, + 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, + 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, + 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, + 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, + 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, + 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, + 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, + 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, + 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, + 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, + 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, + 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, + 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, + 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, + 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, + 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, + 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, + 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, + 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, + 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, + 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, + 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, + 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, + 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, + 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, + 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, + 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, + 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, + 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, + 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, + 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, + 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, + 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, + 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, + 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, + 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, + 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, + 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, + 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, + 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, + 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, + 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, + 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, + 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, + 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, + 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, + 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, + 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, + 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, + 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, + 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, + 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, + 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, + 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, + 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, + 0.82788260f, 0.88168307f, 0.9389798f, 1.0f +}; + + +// @OPTIMIZE: if you want to replace this bresenham line-drawing routine, +// note that you must produce bit-identical output to decode correctly; +// this specific sequence of operations is specified in the spec (it's +// drawing integer-quantized frequency-space lines that the encoder +// expects to be exactly the same) +// ... also, isn't the whole point of Bresenham's algorithm to NOT +// have to divide in the setup? sigh. +#ifndef STB_VORBIS_NO_DEFER_FLOOR +#define LINE_OP(a,b) a *= b +#else +#define LINE_OP(a,b) a = b +#endif + +#ifdef STB_VORBIS_DIVIDE_TABLE +#define DIVTAB_NUMER 32 +#define DIVTAB_DENOM 64 +int8 integer_divide_table[DIVTAB_NUMER][DIVTAB_DENOM]; // 2KB +#endif + +static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y1, int n) +{ + int dy = y1 - y0; + int adx = x1 - x0; + int ady = abs(dy); + int base; + int x=x0,y=y0; + int err = 0; + int sy; + +#ifdef STB_VORBIS_DIVIDE_TABLE + if (adx < DIVTAB_DENOM && ady < DIVTAB_NUMER) { + if (dy < 0) { + base = -integer_divide_table[ady][adx]; + sy = base-1; + } else { + base = integer_divide_table[ady][adx]; + sy = base+1; + } + } else { + base = dy / adx; + if (dy < 0) + sy = base - 1; + else + sy = base+1; + } +#else + base = dy / adx; + if (dy < 0) + sy = base - 1; + else + sy = base+1; +#endif + ady -= abs(base) * adx; + if (x1 > n) x1 = n; + if (x < x1) { + LINE_OP(output[x], inverse_db_table[y&255]); + for (++x; x < x1; ++x) { + err += ady; + if (err >= adx) { + err -= adx; + y += sy; + } else + y += base; + LINE_OP(output[x], inverse_db_table[y&255]); + } + } +} + +static int residue_decode(vorb *f, Codebook *book, float *target, int offset, int n, int rtype) +{ + int k; + if (rtype == 0) { + int step = n / book->dimensions; + for (k=0; k < step; ++k) + if (!codebook_decode_step(f, book, target+offset+k, n-offset-k, step)) + return FALSE; + } else { + for (k=0; k < n; ) { + if (!codebook_decode(f, book, target+offset, n-k)) + return FALSE; + k += book->dimensions; + offset += book->dimensions; + } + } + return TRUE; +} + +// n is 1/2 of the blocksize -- +// specification: "Correct per-vector decode length is [n]/2" +static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) +{ + int i,j,pass; + Residue *r = f->residue_config + rn; + int rtype = f->residue_types[rn]; + int c = r->classbook; + int classwords = f->codebooks[c].dimensions; + unsigned int actual_size = rtype == 2 ? n*2 : n; + unsigned int limit_r_begin = (r->begin < actual_size ? r->begin : actual_size); + unsigned int limit_r_end = (r->end < actual_size ? r->end : actual_size); + int n_read = limit_r_end - limit_r_begin; + int part_read = n_read / r->part_size; + int temp_alloc_point = temp_alloc_save(f); + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + uint8 ***part_classdata = (uint8 ***) temp_block_array(f,f->channels, part_read * sizeof(**part_classdata)); + #else + int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications)); + #endif + + CHECK(f); + + for (i=0; i < ch; ++i) + if (!do_not_decode[i]) + memset(residue_buffers[i], 0, sizeof(float) * n); + + if (rtype == 2 && ch != 1) { + for (j=0; j < ch; ++j) + if (!do_not_decode[j]) + break; + if (j == ch) + goto done; + + for (pass=0; pass < 8; ++pass) { + int pcount = 0, class_set = 0; + if (ch == 2) { + while (pcount < part_read) { + int z = r->begin + pcount*r->part_size; + int c_inter = (z & 1), p_inter = z>>1; + if (pass == 0) { + Codebook *c = f->codebooks+r->classbook; + int q; + DECODE(q,f,c); + if (q == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[0][i+pcount] = q % r->classifications; + q /= r->classifications; + } + #endif + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + int z = r->begin + pcount*r->part_size; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; + #else + int c = classifications[0][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + Codebook *book = f->codebooks + b; + #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + #else + // saves 1% + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + #endif + } else { + z += r->part_size; + c_inter = z & 1; + p_inter = z >> 1; + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } else if (ch > 2) { + while (pcount < part_read) { + int z = r->begin + pcount*r->part_size; + int c_inter = z % ch, p_inter = z/ch; + if (pass == 0) { + Codebook *c = f->codebooks+r->classbook; + int q; + DECODE(q,f,c); + if (q == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[0][i+pcount] = q % r->classifications; + q /= r->classifications; + } + #endif + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + int z = r->begin + pcount*r->part_size; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; + #else + int c = classifications[0][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + Codebook *book = f->codebooks + b; + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + } else { + z += r->part_size; + c_inter = z % ch; + p_inter = z / ch; + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } + } + goto done; + } + CHECK(f); + + for (pass=0; pass < 8; ++pass) { + int pcount = 0, class_set=0; + while (pcount < part_read) { + if (pass == 0) { + for (j=0; j < ch; ++j) { + if (!do_not_decode[j]) { + Codebook *c = f->codebooks+r->classbook; + int temp; + DECODE(temp,f,c); + if (temp == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[j][class_set] = r->classdata[temp]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[j][i+pcount] = temp % r->classifications; + temp /= r->classifications; + } + #endif + } + } + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + for (j=0; j < ch; ++j) { + if (!do_not_decode[j]) { + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[j][class_set][i]; + #else + int c = classifications[j][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + float *target = residue_buffers[j]; + int offset = r->begin + pcount * r->part_size; + int n = r->part_size; + Codebook *book = f->codebooks + b; + if (!residue_decode(f, book, target, offset, n, rtype)) + goto done; + } + } + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } + done: + CHECK(f); + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + temp_free(f,part_classdata); + #else + temp_free(f,classifications); + #endif + temp_alloc_restore(f,temp_alloc_point); +} + + +#if 0 +// slow way for debugging +void inverse_mdct_slow(float *buffer, int n) +{ + int i,j; + int n2 = n >> 1; + float *x = (float *) malloc(sizeof(*x) * n2); + memcpy(x, buffer, sizeof(*x) * n2); + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n2; ++j) + // formula from paper: + //acc += n/4.0f * x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); + // formula from wikipedia + //acc += 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); + // these are equivalent, except the formula from the paper inverts the multiplier! + // however, what actually works is NO MULTIPLIER!?! + //acc += 64 * 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); + acc += x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); + buffer[i] = acc; + } + free(x); +} +#elif 0 +// same as above, but just barely able to run in real time on modern machines +void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) +{ + float mcos[16384]; + int i,j; + int n2 = n >> 1, nmask = (n << 2) -1; + float *x = (float *) malloc(sizeof(*x) * n2); + memcpy(x, buffer, sizeof(*x) * n2); + for (i=0; i < 4*n; ++i) + mcos[i] = (float) cos(M_PI / 2 * i / n); + + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n2; ++j) + acc += x[j] * mcos[(2 * i + 1 + n2)*(2*j+1) & nmask]; + buffer[i] = acc; + } + free(x); +} +#elif 0 +// transform to use a slow dct-iv; this is STILL basically trivial, +// but only requires half as many ops +void dct_iv_slow(float *buffer, int n) +{ + float mcos[16384]; + float x[2048]; + int i,j; + int n2 = n >> 1, nmask = (n << 3) - 1; + memcpy(x, buffer, sizeof(*x) * n); + for (i=0; i < 8*n; ++i) + mcos[i] = (float) cos(M_PI / 4 * i / n); + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n; ++j) + acc += x[j] * mcos[((2 * i + 1)*(2*j+1)) & nmask]; + buffer[i] = acc; + } +} + +void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) +{ + int i, n4 = n >> 2, n2 = n >> 1, n3_4 = n - n4; + float temp[4096]; + + memcpy(temp, buffer, n2 * sizeof(float)); + dct_iv_slow(temp, n2); // returns -c'-d, a-b' + + for (i=0; i < n4 ; ++i) buffer[i] = temp[i+n4]; // a-b' + for ( ; i < n3_4; ++i) buffer[i] = -temp[n3_4 - i - 1]; // b-a', c+d' + for ( ; i < n ; ++i) buffer[i] = -temp[i - n3_4]; // c'+d +} +#endif + +#ifndef LIBVORBIS_MDCT +#define LIBVORBIS_MDCT 0 +#endif + +#if LIBVORBIS_MDCT +// directly call the vorbis MDCT using an interface documented +// by Jeff Roberts... useful for performance comparison +typedef struct +{ + int n; + int log2n; + + float *trig; + int *bitrev; + + float scale; +} mdct_lookup; + +extern void mdct_init(mdct_lookup *lookup, int n); +extern void mdct_clear(mdct_lookup *l); +extern void mdct_backward(mdct_lookup *init, float *in, float *out); + +mdct_lookup M1,M2; + +void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) +{ + mdct_lookup *M; + if (M1.n == n) M = &M1; + else if (M2.n == n) M = &M2; + else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; } + else { + if (M2.n) __asm int 3; + mdct_init(&M2, n); + M = &M2; + } + + mdct_backward(M, buffer, buffer); +} +#endif + + +// the following were split out into separate functions while optimizing; +// they could be pushed back up but eh. __forceinline showed no change; +// they're probably already being inlined. +static void imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A) +{ + float *ee0 = e + i_off; + float *ee2 = ee0 + k_off; + int i; + + assert((n & 3) == 0); + for (i=(n>>2); i > 0; --i) { + float k00_20, k01_21; + k00_20 = ee0[ 0] - ee2[ 0]; + k01_21 = ee0[-1] - ee2[-1]; + ee0[ 0] += ee2[ 0];//ee0[ 0] = ee0[ 0] + ee2[ 0]; + ee0[-1] += ee2[-1];//ee0[-1] = ee0[-1] + ee2[-1]; + ee2[ 0] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-1] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-2] - ee2[-2]; + k01_21 = ee0[-3] - ee2[-3]; + ee0[-2] += ee2[-2];//ee0[-2] = ee0[-2] + ee2[-2]; + ee0[-3] += ee2[-3];//ee0[-3] = ee0[-3] + ee2[-3]; + ee2[-2] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-3] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-4] - ee2[-4]; + k01_21 = ee0[-5] - ee2[-5]; + ee0[-4] += ee2[-4];//ee0[-4] = ee0[-4] + ee2[-4]; + ee0[-5] += ee2[-5];//ee0[-5] = ee0[-5] + ee2[-5]; + ee2[-4] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-5] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-6] - ee2[-6]; + k01_21 = ee0[-7] - ee2[-7]; + ee0[-6] += ee2[-6];//ee0[-6] = ee0[-6] + ee2[-6]; + ee0[-7] += ee2[-7];//ee0[-7] = ee0[-7] + ee2[-7]; + ee2[-6] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-7] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + ee0 -= 8; + ee2 -= 8; + } +} + +static void imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1) +{ + int i; + float k00_20, k01_21; + + float *e0 = e + d0; + float *e2 = e0 + k_off; + + for (i=lim >> 2; i > 0; --i) { + k00_20 = e0[-0] - e2[-0]; + k01_21 = e0[-1] - e2[-1]; + e0[-0] += e2[-0];//e0[-0] = e0[-0] + e2[-0]; + e0[-1] += e2[-1];//e0[-1] = e0[-1] + e2[-1]; + e2[-0] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-1] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-2] - e2[-2]; + k01_21 = e0[-3] - e2[-3]; + e0[-2] += e2[-2];//e0[-2] = e0[-2] + e2[-2]; + e0[-3] += e2[-3];//e0[-3] = e0[-3] + e2[-3]; + e2[-2] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-3] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-4] - e2[-4]; + k01_21 = e0[-5] - e2[-5]; + e0[-4] += e2[-4];//e0[-4] = e0[-4] + e2[-4]; + e0[-5] += e2[-5];//e0[-5] = e0[-5] + e2[-5]; + e2[-4] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-5] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-6] - e2[-6]; + k01_21 = e0[-7] - e2[-7]; + e0[-6] += e2[-6];//e0[-6] = e0[-6] + e2[-6]; + e0[-7] += e2[-7];//e0[-7] = e0[-7] + e2[-7]; + e2[-6] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-7] = (k01_21)*A[0] + (k00_20) * A[1]; + + e0 -= 8; + e2 -= 8; + + A += k1; + } +} + +static void imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0) +{ + int i; + float A0 = A[0]; + float A1 = A[0+1]; + float A2 = A[0+a_off]; + float A3 = A[0+a_off+1]; + float A4 = A[0+a_off*2+0]; + float A5 = A[0+a_off*2+1]; + float A6 = A[0+a_off*3+0]; + float A7 = A[0+a_off*3+1]; + + float k00,k11; + + float *ee0 = e +i_off; + float *ee2 = ee0+k_off; + + for (i=n; i > 0; --i) { + k00 = ee0[ 0] - ee2[ 0]; + k11 = ee0[-1] - ee2[-1]; + ee0[ 0] = ee0[ 0] + ee2[ 0]; + ee0[-1] = ee0[-1] + ee2[-1]; + ee2[ 0] = (k00) * A0 - (k11) * A1; + ee2[-1] = (k11) * A0 + (k00) * A1; + + k00 = ee0[-2] - ee2[-2]; + k11 = ee0[-3] - ee2[-3]; + ee0[-2] = ee0[-2] + ee2[-2]; + ee0[-3] = ee0[-3] + ee2[-3]; + ee2[-2] = (k00) * A2 - (k11) * A3; + ee2[-3] = (k11) * A2 + (k00) * A3; + + k00 = ee0[-4] - ee2[-4]; + k11 = ee0[-5] - ee2[-5]; + ee0[-4] = ee0[-4] + ee2[-4]; + ee0[-5] = ee0[-5] + ee2[-5]; + ee2[-4] = (k00) * A4 - (k11) * A5; + ee2[-5] = (k11) * A4 + (k00) * A5; + + k00 = ee0[-6] - ee2[-6]; + k11 = ee0[-7] - ee2[-7]; + ee0[-6] = ee0[-6] + ee2[-6]; + ee0[-7] = ee0[-7] + ee2[-7]; + ee2[-6] = (k00) * A6 - (k11) * A7; + ee2[-7] = (k11) * A6 + (k00) * A7; + + ee0 -= k0; + ee2 -= k0; + } +} + +static __forceinline void iter_54(float *z) +{ + float k00,k11,k22,k33; + float y0,y1,y2,y3; + + k00 = z[ 0] - z[-4]; + y0 = z[ 0] + z[-4]; + y2 = z[-2] + z[-6]; + k22 = z[-2] - z[-6]; + + z[-0] = y0 + y2; // z0 + z4 + z2 + z6 + z[-2] = y0 - y2; // z0 + z4 - z2 - z6 + + // done with y0,y2 + + k33 = z[-3] - z[-7]; + + z[-4] = k00 + k33; // z0 - z4 + z3 - z7 + z[-6] = k00 - k33; // z0 - z4 - z3 + z7 + + // done with k33 + + k11 = z[-1] - z[-5]; + y1 = z[-1] + z[-5]; + y3 = z[-3] + z[-7]; + + z[-1] = y1 + y3; // z1 + z5 + z3 + z7 + z[-3] = y1 - y3; // z1 + z5 - z3 - z7 + z[-5] = k11 - k22; // z1 - z5 + z2 - z6 + z[-7] = k11 + k22; // z1 - z5 - z2 + z6 +} + +static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n) +{ + int a_off = base_n >> 3; + float A2 = A[0+a_off]; + float *z = e + i_off; + float *base = z - 16 * n; + + while (z > base) { + float k00,k11; + float l00,l11; + + k00 = z[-0] - z[ -8]; + k11 = z[-1] - z[ -9]; + l00 = z[-2] - z[-10]; + l11 = z[-3] - z[-11]; + z[ -0] = z[-0] + z[ -8]; + z[ -1] = z[-1] + z[ -9]; + z[ -2] = z[-2] + z[-10]; + z[ -3] = z[-3] + z[-11]; + z[ -8] = k00; + z[ -9] = k11; + z[-10] = (l00+l11) * A2; + z[-11] = (l11-l00) * A2; + + k00 = z[ -4] - z[-12]; + k11 = z[ -5] - z[-13]; + l00 = z[ -6] - z[-14]; + l11 = z[ -7] - z[-15]; + z[ -4] = z[ -4] + z[-12]; + z[ -5] = z[ -5] + z[-13]; + z[ -6] = z[ -6] + z[-14]; + z[ -7] = z[ -7] + z[-15]; + z[-12] = k11; + z[-13] = -k00; + z[-14] = (l11-l00) * A2; + z[-15] = (l00+l11) * -A2; + + iter_54(z); + iter_54(z-8); + z -= 16; + } +} + +static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) +{ + int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; + int ld; + // @OPTIMIZE: reduce register pressure by using fewer variables? + int save_point = temp_alloc_save(f); + float *buf2 = (float *) temp_alloc(f, n2 * sizeof(*buf2)); + float *u=NULL,*v=NULL; + // twiddle factors + float *A = f->A[blocktype]; + + // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" + // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function. + + // kernel from paper + + + // merged: + // copy and reflect spectral data + // step 0 + + // note that it turns out that the items added together during + // this step are, in fact, being added to themselves (as reflected + // by step 0). inexplicable inefficiency! this became obvious + // once I combined the passes. + + // so there's a missing 'times 2' here (for adding X to itself). + // this propagates through linearly to the end, where the numbers + // are 1/2 too small, and need to be compensated for. + + { + float *d,*e, *AA, *e_stop; + d = &buf2[n2-2]; + AA = A; + e = &buffer[0]; + e_stop = &buffer[n2]; + while (e != e_stop) { + d[1] = (e[0] * AA[0] - e[2]*AA[1]); + d[0] = (e[0] * AA[1] + e[2]*AA[0]); + d -= 2; + AA += 2; + e += 4; + } + + e = &buffer[n2-3]; + while (d >= buf2) { + d[1] = (-e[2] * AA[0] - -e[0]*AA[1]); + d[0] = (-e[2] * AA[1] + -e[0]*AA[0]); + d -= 2; + AA += 2; + e -= 4; + } + } + + // now we use symbolic names for these, so that we can + // possibly swap their meaning as we change which operations + // are in place + + u = buffer; + v = buf2; + + // step 2 (paper output is w, now u) + // this could be in place, but the data ends up in the wrong + // place... _somebody_'s got to swap it, so this is nominated + { + float *AA = &A[n2-8]; + float *d0,*d1, *e0, *e1; + + e0 = &v[n4]; + e1 = &v[0]; + + d0 = &u[n4]; + d1 = &u[0]; + + while (AA >= A) { + float v40_20, v41_21; + + v41_21 = e0[1] - e1[1]; + v40_20 = e0[0] - e1[0]; + d0[1] = e0[1] + e1[1]; + d0[0] = e0[0] + e1[0]; + d1[1] = v41_21*AA[4] - v40_20*AA[5]; + d1[0] = v40_20*AA[4] + v41_21*AA[5]; + + v41_21 = e0[3] - e1[3]; + v40_20 = e0[2] - e1[2]; + d0[3] = e0[3] + e1[3]; + d0[2] = e0[2] + e1[2]; + d1[3] = v41_21*AA[0] - v40_20*AA[1]; + d1[2] = v40_20*AA[0] + v41_21*AA[1]; + + AA -= 8; + + d0 += 4; + d1 += 4; + e0 += 4; + e1 += 4; + } + } + + // step 3 + ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + + // optimized step 3: + + // the original step3 loop can be nested r inside s or s inside r; + // it's written originally as s inside r, but this is dumb when r + // iterates many times, and s few. So I have two copies of it and + // switch between them halfway. + + // this is iteration 0 of step 3 + imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n >> 3), A); + imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n >> 3), A); + + // this is iteration 1 of step 3 + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n >> 4), A, 16); + + l=2; + for (; l < (ld-3)>>1; ++l) { + int k0 = n >> (l+2), k0_2 = k0>>1; + int lim = 1 << (l+1); + int i; + for (i=0; i < lim; ++i) + imdct_step3_inner_r_loop(n >> (l+4), u, n2-1 - k0*i, -k0_2, A, 1 << (l+3)); + } + + for (; l < ld-6; ++l) { + int k0 = n >> (l+2), k1 = 1 << (l+3), k0_2 = k0>>1; + int rlim = n >> (l+6), r; + int lim = 1 << (l+1); + int i_off; + float *A0 = A; + i_off = n2-1; + for (r=rlim; r > 0; --r) { + imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0); + A0 += k1*4; + i_off -= 8; + } + } + + // iterations with count: + // ld-6,-5,-4 all interleaved together + // the big win comes from getting rid of needless flops + // due to the constants on pass 5 & 4 being all 1 and 0; + // combining them to be simultaneous to improve cache made little difference + imdct_step3_inner_s_loop_ld654(n >> 5, u, n2-1, A, n); + + // output is u + + // step 4, 5, and 6 + // cannot be in-place because of step 5 + { + uint16 *bitrev = f->bit_reverse[blocktype]; + // weirdly, I'd have thought reading sequentially and writing + // erratically would have been better than vice-versa, but in + // fact that's not what my testing showed. (That is, with + // j = bitreverse(i), do you read i and write j, or read j and write i.) + + float *d0 = &v[n4-4]; + float *d1 = &v[n2-4]; + while (d0 >= v) { + int k4; + + k4 = bitrev[0]; + d1[3] = u[k4+0]; + d1[2] = u[k4+1]; + d0[3] = u[k4+2]; + d0[2] = u[k4+3]; + + k4 = bitrev[1]; + d1[1] = u[k4+0]; + d1[0] = u[k4+1]; + d0[1] = u[k4+2]; + d0[0] = u[k4+3]; + + d0 -= 4; + d1 -= 4; + bitrev += 2; + } + } + // (paper output is u, now v) + + + // data must be in buf2 + assert(v == buf2); + + // step 7 (paper output is v, now v) + // this is now in place + { + float *C = f->C[blocktype]; + float *d, *e; + + d = v; + e = v + n2 - 4; + + while (d < e) { + float a02,a11,b0,b1,b2,b3; + + a02 = d[0] - e[2]; + a11 = d[1] + e[3]; + + b0 = C[1]*a02 + C[0]*a11; + b1 = C[1]*a11 - C[0]*a02; + + b2 = d[0] + e[ 2]; + b3 = d[1] - e[ 3]; + + d[0] = b2 + b0; + d[1] = b3 + b1; + e[2] = b2 - b0; + e[3] = b1 - b3; + + a02 = d[2] - e[0]; + a11 = d[3] + e[1]; + + b0 = C[3]*a02 + C[2]*a11; + b1 = C[3]*a11 - C[2]*a02; + + b2 = d[2] + e[ 0]; + b3 = d[3] - e[ 1]; + + d[2] = b2 + b0; + d[3] = b3 + b1; + e[0] = b2 - b0; + e[1] = b1 - b3; + + C += 4; + d += 4; + e -= 4; + } + } + + // data must be in buf2 + + + // step 8+decode (paper output is X, now buffer) + // this generates pairs of data a la 8 and pushes them directly through + // the decode kernel (pushing rather than pulling) to avoid having + // to make another pass later + + // this cannot POSSIBLY be in place, so we refer to the buffers directly + + { + float *d0,*d1,*d2,*d3; + + float *B = f->B[blocktype] + n2 - 8; + float *e = buf2 + n2 - 8; + d0 = &buffer[0]; + d1 = &buffer[n2-4]; + d2 = &buffer[n2]; + d3 = &buffer[n-4]; + while (e >= v) { + float p0,p1,p2,p3; + + p3 = e[6]*B[7] - e[7]*B[6]; + p2 = -e[6]*B[6] - e[7]*B[7]; + + d0[0] = p3; + d1[3] = - p3; + d2[0] = p2; + d3[3] = p2; + + p1 = e[4]*B[5] - e[5]*B[4]; + p0 = -e[4]*B[4] - e[5]*B[5]; + + d0[1] = p1; + d1[2] = - p1; + d2[1] = p0; + d3[2] = p0; + + p3 = e[2]*B[3] - e[3]*B[2]; + p2 = -e[2]*B[2] - e[3]*B[3]; + + d0[2] = p3; + d1[1] = - p3; + d2[2] = p2; + d3[1] = p2; + + p1 = e[0]*B[1] - e[1]*B[0]; + p0 = -e[0]*B[0] - e[1]*B[1]; + + d0[3] = p1; + d1[0] = - p1; + d2[3] = p0; + d3[0] = p0; + + B -= 8; + e -= 8; + d0 += 4; + d2 += 4; + d1 -= 4; + d3 -= 4; + } + } + + temp_free(f,buf2); + temp_alloc_restore(f,save_point); +} + +#if 0 +// this is the original version of the above code, if you want to optimize it from scratch +void inverse_mdct_naive(float *buffer, int n) +{ + float s; + float A[1 << 12], B[1 << 12], C[1 << 11]; + int i,k,k2,k4, n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; + int n3_4 = n - n4, ld; + // how can they claim this only uses N words?! + // oh, because they're only used sparsely, whoops + float u[1 << 13], X[1 << 13], v[1 << 13], w[1 << 13]; + // set up twiddle factors + + for (k=k2=0; k < n4; ++k,k2+=2) { + A[k2 ] = (float) cos(4*k*M_PI/n); + A[k2+1] = (float) -sin(4*k*M_PI/n); + B[k2 ] = (float) cos((k2+1)*M_PI/n/2); + B[k2+1] = (float) sin((k2+1)*M_PI/n/2); + } + for (k=k2=0; k < n8; ++k,k2+=2) { + C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); + C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); + } + + // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" + // Note there are bugs in that pseudocode, presumably due to them attempting + // to rename the arrays nicely rather than representing the way their actual + // implementation bounces buffers back and forth. As a result, even in the + // "some formulars corrected" version, a direct implementation fails. These + // are noted below as "paper bug". + + // copy and reflect spectral data + for (k=0; k < n2; ++k) u[k] = buffer[k]; + for ( ; k < n ; ++k) u[k] = -buffer[n - k - 1]; + // kernel from paper + // step 1 + for (k=k2=k4=0; k < n4; k+=1, k2+=2, k4+=4) { + v[n-k4-1] = (u[k4] - u[n-k4-1]) * A[k2] - (u[k4+2] - u[n-k4-3])*A[k2+1]; + v[n-k4-3] = (u[k4] - u[n-k4-1]) * A[k2+1] + (u[k4+2] - u[n-k4-3])*A[k2]; + } + // step 2 + for (k=k4=0; k < n8; k+=1, k4+=4) { + w[n2+3+k4] = v[n2+3+k4] + v[k4+3]; + w[n2+1+k4] = v[n2+1+k4] + v[k4+1]; + w[k4+3] = (v[n2+3+k4] - v[k4+3])*A[n2-4-k4] - (v[n2+1+k4]-v[k4+1])*A[n2-3-k4]; + w[k4+1] = (v[n2+1+k4] - v[k4+1])*A[n2-4-k4] + (v[n2+3+k4]-v[k4+3])*A[n2-3-k4]; + } + // step 3 + ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + for (l=0; l < ld-3; ++l) { + int k0 = n >> (l+2), k1 = 1 << (l+3); + int rlim = n >> (l+4), r4, r; + int s2lim = 1 << (l+2), s2; + for (r=r4=0; r < rlim; r4+=4,++r) { + for (s2=0; s2 < s2lim; s2+=2) { + u[n-1-k0*s2-r4] = w[n-1-k0*s2-r4] + w[n-1-k0*(s2+1)-r4]; + u[n-3-k0*s2-r4] = w[n-3-k0*s2-r4] + w[n-3-k0*(s2+1)-r4]; + u[n-1-k0*(s2+1)-r4] = (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1] + - (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1+1]; + u[n-3-k0*(s2+1)-r4] = (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1] + + (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1+1]; + } + } + if (l+1 < ld-3) { + // paper bug: ping-ponging of u&w here is omitted + memcpy(w, u, sizeof(u)); + } + } + + // step 4 + for (i=0; i < n8; ++i) { + int j = bit_reverse(i) >> (32-ld+3); + assert(j < n8); + if (i == j) { + // paper bug: original code probably swapped in place; if copying, + // need to directly copy in this case + int i8 = i << 3; + v[i8+1] = u[i8+1]; + v[i8+3] = u[i8+3]; + v[i8+5] = u[i8+5]; + v[i8+7] = u[i8+7]; + } else if (i < j) { + int i8 = i << 3, j8 = j << 3; + v[j8+1] = u[i8+1], v[i8+1] = u[j8 + 1]; + v[j8+3] = u[i8+3], v[i8+3] = u[j8 + 3]; + v[j8+5] = u[i8+5], v[i8+5] = u[j8 + 5]; + v[j8+7] = u[i8+7], v[i8+7] = u[j8 + 7]; + } + } + // step 5 + for (k=0; k < n2; ++k) { + w[k] = v[k*2+1]; + } + // step 6 + for (k=k2=k4=0; k < n8; ++k, k2 += 2, k4 += 4) { + u[n-1-k2] = w[k4]; + u[n-2-k2] = w[k4+1]; + u[n3_4 - 1 - k2] = w[k4+2]; + u[n3_4 - 2 - k2] = w[k4+3]; + } + // step 7 + for (k=k2=0; k < n8; ++k, k2 += 2) { + v[n2 + k2 ] = ( u[n2 + k2] + u[n-2-k2] + C[k2+1]*(u[n2+k2]-u[n-2-k2]) + C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; + v[n-2 - k2] = ( u[n2 + k2] + u[n-2-k2] - C[k2+1]*(u[n2+k2]-u[n-2-k2]) - C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; + v[n2+1+ k2] = ( u[n2+1+k2] - u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; + v[n-1 - k2] = (-u[n2+1+k2] + u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; + } + // step 8 + for (k=k2=0; k < n4; ++k,k2 += 2) { + X[k] = v[k2+n2]*B[k2 ] + v[k2+1+n2]*B[k2+1]; + X[n2-1-k] = v[k2+n2]*B[k2+1] - v[k2+1+n2]*B[k2 ]; + } + + // decode kernel to output + // determined the following value experimentally + // (by first figuring out what made inverse_mdct_slow work); then matching that here + // (probably vorbis encoder premultiplies by n or n/2, to save it on the decoder?) + s = 0.5; // theoretically would be n4 + + // [[[ note! the s value of 0.5 is compensated for by the B[] in the current code, + // so it needs to use the "old" B values to behave correctly, or else + // set s to 1.0 ]]] + for (i=0; i < n4 ; ++i) buffer[i] = s * X[i+n4]; + for ( ; i < n3_4; ++i) buffer[i] = -s * X[n3_4 - i - 1]; + for ( ; i < n ; ++i) buffer[i] = -s * X[i - n3_4]; +} +#endif + +static float *get_window(vorb *f, int len) +{ + len <<= 1; + if (len == f->blocksize_0) return f->window[0]; + if (len == f->blocksize_1) return f->window[1]; + return NULL; +} + +#ifndef STB_VORBIS_NO_DEFER_FLOOR +typedef int16 YTYPE; +#else +typedef int YTYPE; +#endif +static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *finalY, uint8 *step2_flag) +{ + int n2 = n >> 1; + int s = map->chan[i].mux, floor; + floor = map->submap_floor[s]; + if (f->floor_types[floor] == 0) { + return error(f, VORBIS_invalid_stream); + } else { + Floor1 *g = &f->floor_config[floor].floor1; + int j,q; + int lx = 0, ly = finalY[0] * g->floor1_multiplier; + for (q=1; q < g->values; ++q) { + j = g->sorted_order[q]; + #ifndef STB_VORBIS_NO_DEFER_FLOOR + STBV_NOTUSED(step2_flag); + if (finalY[j] >= 0) + #else + if (step2_flag[j]) + #endif + { + int hy = finalY[j] * g->floor1_multiplier; + int hx = g->Xlist[j]; + if (lx != hx) + draw_line(target, lx,ly, hx,hy, n2); + CHECK(f); + lx = hx, ly = hy; + } + } + if (lx < n2) { + // optimization of: draw_line(target, lx,ly, n,ly, n2); + for (j=lx; j < n2; ++j) + LINE_OP(target[j], inverse_db_table[ly]); + CHECK(f); + } + } + return TRUE; +} + +// The meaning of "left" and "right" +// +// For a given frame: +// we compute samples from 0..n +// window_center is n/2 +// we'll window and mix the samples from left_start to left_end with data from the previous frame +// all of the samples from left_end to right_start can be output without mixing; however, +// this interval is 0-length except when transitioning between short and long frames +// all of the samples from right_start to right_end need to be mixed with the next frame, +// which we don't have, so those get saved in a buffer +// frame N's right_end-right_start, the number of samples to mix with the next frame, +// has to be the same as frame N+1's left_end-left_start (which they are by +// construction) + +static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) +{ + Mode *m; + int i, n, prev, next, window_center; + f->channel_buffer_start = f->channel_buffer_end = 0; + + retry: + if (f->eof) return FALSE; + if (!maybe_start_packet(f)) + return FALSE; + // check packet type + if (get_bits(f,1) != 0) { + if (IS_PUSH_MODE(f)) + return error(f,VORBIS_bad_packet_type); + while (EOP != get8_packet(f)); + goto retry; + } + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + + i = get_bits(f, ilog(f->mode_count-1)); + if (i == EOP) return FALSE; + if (i >= f->mode_count) return FALSE; + *mode = i; + m = f->mode_config + i; + if (m->blockflag) { + n = f->blocksize_1; + prev = get_bits(f,1); + next = get_bits(f,1); + } else { + prev = next = 0; + n = f->blocksize_0; + } + +// WINDOWING + + window_center = n >> 1; + if (m->blockflag && !prev) { + *p_left_start = (n - f->blocksize_0) >> 2; + *p_left_end = (n + f->blocksize_0) >> 2; + } else { + *p_left_start = 0; + *p_left_end = window_center; + } + if (m->blockflag && !next) { + *p_right_start = (n*3 - f->blocksize_0) >> 2; + *p_right_end = (n*3 + f->blocksize_0) >> 2; + } else { + *p_right_start = window_center; + *p_right_end = n; + } + + return TRUE; +} + +static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, int left_end, int right_start, int right_end, int *p_left) +{ + Mapping *map; + int i,j,k,n,n2; + int zero_channel[256]; + int really_zero_channel[256]; + +// WINDOWING + + STBV_NOTUSED(left_end); + n = f->blocksize[m->blockflag]; + map = &f->mapping[m->mapping]; + +// FLOORS + n2 = n >> 1; + + CHECK(f); + + for (i=0; i < f->channels; ++i) { + int s = map->chan[i].mux, floor; + zero_channel[i] = FALSE; + floor = map->submap_floor[s]; + if (f->floor_types[floor] == 0) { + return error(f, VORBIS_invalid_stream); + } else { + Floor1 *g = &f->floor_config[floor].floor1; + if (get_bits(f, 1)) { + short *finalY; + uint8 step2_flag[256]; + static int range_list[4] = { 256, 128, 86, 64 }; + int range = range_list[g->floor1_multiplier-1]; + int offset = 2; + finalY = f->finalY[i]; + finalY[0] = get_bits(f, ilog(range)-1); + finalY[1] = get_bits(f, ilog(range)-1); + for (j=0; j < g->partitions; ++j) { + int pclass = g->partition_class_list[j]; + int cdim = g->class_dimensions[pclass]; + int cbits = g->class_subclasses[pclass]; + int csub = (1 << cbits)-1; + int cval = 0; + if (cbits) { + Codebook *c = f->codebooks + g->class_masterbooks[pclass]; + DECODE(cval,f,c); + } + for (k=0; k < cdim; ++k) { + int book = g->subclass_books[pclass][cval & csub]; + cval = cval >> cbits; + if (book >= 0) { + int temp; + Codebook *c = f->codebooks + book; + DECODE(temp,f,c); + finalY[offset++] = temp; + } else + finalY[offset++] = 0; + } + } + if (f->valid_bits == INVALID_BITS) goto error; // behavior according to spec + step2_flag[0] = step2_flag[1] = 1; + for (j=2; j < g->values; ++j) { + int low, high, pred, highroom, lowroom, room, val; + low = g->neighbors[j][0]; + high = g->neighbors[j][1]; + //neighbors(g->Xlist, j, &low, &high); + pred = predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]); + val = finalY[j]; + highroom = range - pred; + lowroom = pred; + if (highroom < lowroom) + room = highroom * 2; + else + room = lowroom * 2; + if (val) { + step2_flag[low] = step2_flag[high] = 1; + step2_flag[j] = 1; + if (val >= room) + if (highroom > lowroom) + finalY[j] = val - lowroom + pred; + else + finalY[j] = pred - val + highroom - 1; + else + if (val & 1) + finalY[j] = pred - ((val+1)>>1); + else + finalY[j] = pred + (val>>1); + } else { + step2_flag[j] = 0; + finalY[j] = pred; + } + } + +#ifdef STB_VORBIS_NO_DEFER_FLOOR + do_floor(f, map, i, n, f->floor_buffers[i], finalY, step2_flag); +#else + // defer final floor computation until _after_ residue + for (j=0; j < g->values; ++j) { + if (!step2_flag[j]) + finalY[j] = -1; + } +#endif + } else { + error: + zero_channel[i] = TRUE; + } + // So we just defer everything else to later + + // at this point we've decoded the floor into buffer + } + } + CHECK(f); + // at this point we've decoded all floors + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + + // re-enable coupled channels if necessary + memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels); + for (i=0; i < map->coupling_steps; ++i) + if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) { + zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE; + } + + CHECK(f); +// RESIDUE DECODE + for (i=0; i < map->submaps; ++i) { + float *residue_buffers[STB_VORBIS_MAX_CHANNELS]; + int r; + uint8 do_not_decode[256]; + int ch = 0; + for (j=0; j < f->channels; ++j) { + if (map->chan[j].mux == i) { + if (zero_channel[j]) { + do_not_decode[ch] = TRUE; + residue_buffers[ch] = NULL; + } else { + do_not_decode[ch] = FALSE; + residue_buffers[ch] = f->channel_buffers[j]; + } + ++ch; + } + } + r = map->submap_residue[i]; + decode_residue(f, residue_buffers, ch, n2, r, do_not_decode); + } + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + CHECK(f); + +// INVERSE COUPLING + for (i = map->coupling_steps-1; i >= 0; --i) { + int n2 = n >> 1; + float *m = f->channel_buffers[map->chan[i].magnitude]; + float *a = f->channel_buffers[map->chan[i].angle ]; + for (j=0; j < n2; ++j) { + float a2,m2; + if (m[j] > 0) + if (a[j] > 0) + m2 = m[j], a2 = m[j] - a[j]; + else + a2 = m[j], m2 = m[j] + a[j]; + else + if (a[j] > 0) + m2 = m[j], a2 = m[j] + a[j]; + else + a2 = m[j], m2 = m[j] - a[j]; + m[j] = m2; + a[j] = a2; + } + } + CHECK(f); + + // finish decoding the floors +#ifndef STB_VORBIS_NO_DEFER_FLOOR + for (i=0; i < f->channels; ++i) { + if (really_zero_channel[i]) { + memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); + } else { + do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL); + } + } +#else + for (i=0; i < f->channels; ++i) { + if (really_zero_channel[i]) { + memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); + } else { + for (j=0; j < n2; ++j) + f->channel_buffers[i][j] *= f->floor_buffers[i][j]; + } + } +#endif + +// INVERSE MDCT + CHECK(f); + for (i=0; i < f->channels; ++i) + inverse_mdct(f->channel_buffers[i], n, f, m->blockflag); + CHECK(f); + + // this shouldn't be necessary, unless we exited on an error + // and want to flush to get to the next packet + flush_packet(f); + + if (f->first_decode) { + // assume we start so first non-discarded sample is sample 0 + // this isn't to spec, but spec would require us to read ahead + // and decode the size of all current frames--could be done, + // but presumably it's not a commonly used feature + f->current_loc = 0u - n2; // start of first frame is positioned for discard (NB this is an intentional unsigned overflow/wrap-around) + // we might have to discard samples "from" the next frame too, + // if we're lapping a large block then a small at the start? + f->discard_samples_deferred = n - right_end; + f->current_loc_valid = TRUE; + f->first_decode = FALSE; + } else if (f->discard_samples_deferred) { + if (f->discard_samples_deferred >= right_start - left_start) { + f->discard_samples_deferred -= (right_start - left_start); + left_start = right_start; + *p_left = left_start; + } else { + left_start += f->discard_samples_deferred; + *p_left = left_start; + f->discard_samples_deferred = 0; + } + } else if (f->previous_length == 0 && f->current_loc_valid) { + // we're recovering from a seek... that means we're going to discard + // the samples from this packet even though we know our position from + // the last page header, so we need to update the position based on + // the discarded samples here + // but wait, the code below is going to add this in itself even + // on a discard, so we don't need to do it here... + } + + // check if we have ogg information about the sample # for this packet + if (f->last_seg_which == f->end_seg_with_known_loc) { + // if we have a valid current loc, and this is final: + if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { + uint32 current_end = f->known_loc_for_packet; + // then let's infer the size of the (probably) short final frame + if (current_end < f->current_loc + (right_end-left_start)) { + if (current_end < f->current_loc) { + // negative truncation, that's impossible! + *len = 0; + } else { + *len = current_end - f->current_loc; + } + *len += left_start; // this doesn't seem right, but has no ill effect on my test files + if (*len > right_end) *len = right_end; // this should never happen + f->current_loc += *len; + return TRUE; + } + } + // otherwise, just set our sample loc + // guess that the ogg granule pos refers to the _middle_ of the + // last frame? + // set f->current_loc to the position of left_start + f->current_loc = f->known_loc_for_packet - (n2-left_start); + f->current_loc_valid = TRUE; + } + if (f->current_loc_valid) + f->current_loc += (right_start - left_start); + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + *len = right_end; // ignore samples after the window goes to 0 + CHECK(f); + + return TRUE; +} + +static int vorbis_decode_packet(vorb *f, int *len, int *p_left, int *p_right) +{ + int mode, left_end, right_end; + if (!vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0; + return vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left); +} + +static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right) +{ + int prev,i,j; + // we use right&left (the start of the right- and left-window sin()-regions) + // to determine how much to return, rather than inferring from the rules + // (same result, clearer code); 'left' indicates where our sin() window + // starts, therefore where the previous window's right edge starts, and + // therefore where to start mixing from the previous buffer. 'right' + // indicates where our sin() ending-window starts, therefore that's where + // we start saving, and where our returned-data ends. + + // mixin from previous window + if (f->previous_length) { + int i,j, n = f->previous_length; + float *w = get_window(f, n); + if (w == NULL) return 0; + for (i=0; i < f->channels; ++i) { + for (j=0; j < n; ++j) + f->channel_buffers[i][left+j] = + f->channel_buffers[i][left+j]*w[ j] + + f->previous_window[i][ j]*w[n-1-j]; + } + } + + prev = f->previous_length; + + // last half of this data becomes previous window + f->previous_length = len - right; + + // @OPTIMIZE: could avoid this copy by double-buffering the + // output (flipping previous_window with channel_buffers), but + // then previous_window would have to be 2x as large, and + // channel_buffers couldn't be temp mem (although they're NOT + // currently temp mem, they could be (unless we want to level + // performance by spreading out the computation)) + for (i=0; i < f->channels; ++i) + for (j=0; right+j < len; ++j) + f->previous_window[i][j] = f->channel_buffers[i][right+j]; + + if (!prev) + // there was no previous packet, so this data isn't valid... + // this isn't entirely true, only the would-have-overlapped data + // isn't valid, but this seems to be what the spec requires + return 0; + + // truncate a short frame + if (len < right) right = len; + + f->samples_output += right-left; + + return right - left; +} + +static int vorbis_pump_first_frame(stb_vorbis *f) +{ + int len, right, left, res; + res = vorbis_decode_packet(f, &len, &left, &right); + if (res) + vorbis_finish_frame(f, len, left, right); + return res; +} + +#ifndef STB_VORBIS_NO_PUSHDATA_API +static int is_whole_packet_present(stb_vorbis *f) +{ + // make sure that we have the packet available before continuing... + // this requires a full ogg parse, but we know we can fetch from f->stream + + // instead of coding this out explicitly, we could save the current read state, + // read the next packet with get8() until end-of-packet, check f->eof, then + // reset the state? but that would be slower, esp. since we'd have over 256 bytes + // of state to restore (primarily the page segment table) + + int s = f->next_seg, first = TRUE; + uint8 *p = f->stream; + + if (s != -1) { // if we're not starting the packet with a 'continue on next page' flag + for (; s < f->segment_count; ++s) { + p += f->segments[s]; + if (f->segments[s] < 255) // stop at first short segment + break; + } + // either this continues, or it ends it... + if (s == f->segment_count) + s = -1; // set 'crosses page' flag + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + first = FALSE; + } + for (; s == -1;) { + uint8 *q; + int n; + + // check that we have the page header ready + if (p + 26 >= f->stream_end) return error(f, VORBIS_need_more_data); + // validate the page + if (memcmp(p, ogg_page_header, 4)) return error(f, VORBIS_invalid_stream); + if (p[4] != 0) return error(f, VORBIS_invalid_stream); + if (first) { // the first segment must NOT have 'continued_packet', later ones MUST + if (f->previous_length) + if ((p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); + // if no previous length, we're resynching, so we can come in on a continued-packet, + // which we'll just drop + } else { + if (!(p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); + } + n = p[26]; // segment counts + q = p+27; // q points to segment table + p = q + n; // advance past header + // make sure we've read the segment table + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + for (s=0; s < n; ++s) { + p += q[s]; + if (q[s] < 255) + break; + } + if (s == n) + s = -1; // set 'crosses page' flag + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + first = FALSE; + } + return TRUE; +} +#endif // !STB_VORBIS_NO_PUSHDATA_API + +static int start_decoder(vorb *f) +{ + uint8 header[6], x,y; + int len,i,j,k, max_submaps = 0; + int longest_floorlist=0; + + // first page, first packet + f->first_decode = TRUE; + + if (!start_page(f)) return FALSE; + // validate page flag + if (!(f->page_flag & PAGEFLAG_first_page)) return error(f, VORBIS_invalid_first_page); + if (f->page_flag & PAGEFLAG_last_page) return error(f, VORBIS_invalid_first_page); + if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page); + // check for expected packet length + if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page); + if (f->segments[0] != 30) { + // check for the Ogg skeleton fishead identifying header to refine our error + if (f->segments[0] == 64 && + getn(f, header, 6) && + header[0] == 'f' && + header[1] == 'i' && + header[2] == 's' && + header[3] == 'h' && + header[4] == 'e' && + header[5] == 'a' && + get8(f) == 'd' && + get8(f) == '\0') return error(f, VORBIS_ogg_skeleton_not_supported); + else + return error(f, VORBIS_invalid_first_page); + } + + // read packet + // check packet header + if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page); + if (!getn(f, header, 6)) return error(f, VORBIS_unexpected_eof); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_first_page); + // vorbis_version + if (get32(f) != 0) return error(f, VORBIS_invalid_first_page); + f->channels = get8(f); if (!f->channels) return error(f, VORBIS_invalid_first_page); + if (f->channels > STB_VORBIS_MAX_CHANNELS) return error(f, VORBIS_too_many_channels); + f->sample_rate = get32(f); if (!f->sample_rate) return error(f, VORBIS_invalid_first_page); + get32(f); // bitrate_maximum + get32(f); // bitrate_nominal + get32(f); // bitrate_minimum + x = get8(f); + { + int log0,log1; + log0 = x & 15; + log1 = x >> 4; + f->blocksize_0 = 1 << log0; + f->blocksize_1 = 1 << log1; + if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup); + if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup); + if (log0 > log1) return error(f, VORBIS_invalid_setup); + } + + // framing_flag + x = get8(f); + if (!(x & 1)) return error(f, VORBIS_invalid_first_page); + + // second packet! + if (!start_page(f)) return FALSE; + + if (!start_packet(f)) return FALSE; + + if (!next_segment(f)) return FALSE; + + if (get8_packet(f) != VORBIS_packet_comment) return error(f, VORBIS_invalid_setup); + for (i=0; i < 6; ++i) header[i] = get8_packet(f); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); + //file vendor + len = get32_packet(f); + f->vendor = (char*)setup_malloc(f, sizeof(char) * (len+1)); + if (f->vendor == NULL) return error(f, VORBIS_outofmem); + for(i=0; i < len; ++i) { + f->vendor[i] = get8_packet(f); + } + f->vendor[len] = (char)'\0'; + //user comments + f->comment_list_length = get32_packet(f); + f->comment_list = NULL; + if (f->comment_list_length > 0) + { + f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); + if (f->comment_list == NULL) return error(f, VORBIS_outofmem); + } + + for(i=0; i < f->comment_list_length; ++i) { + len = get32_packet(f); + f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1)); + if (f->comment_list[i] == NULL) return error(f, VORBIS_outofmem); + + for(j=0; j < len; ++j) { + f->comment_list[i][j] = get8_packet(f); + } + f->comment_list[i][len] = (char)'\0'; + } + + // framing_flag + x = get8_packet(f); + if (!(x & 1)) return error(f, VORBIS_invalid_setup); + + + skip(f, f->bytes_in_seg); + f->bytes_in_seg = 0; + + do { + len = next_segment(f); + skip(f, len); + f->bytes_in_seg = 0; + } while (len); + + // third packet! + if (!start_packet(f)) return FALSE; + + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (IS_PUSH_MODE(f)) { + if (!is_whole_packet_present(f)) { + // convert error in ogg header to write type + if (f->error == VORBIS_invalid_stream) + f->error = VORBIS_invalid_setup; + return FALSE; + } + } + #endif + + crc32_init(); // always init it, to avoid multithread race conditions + + if (get8_packet(f) != VORBIS_packet_setup) return error(f, VORBIS_invalid_setup); + for (i=0; i < 6; ++i) header[i] = get8_packet(f); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); + + // codebooks + + f->codebook_count = get_bits(f,8) + 1; + f->codebooks = (Codebook *) setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count); + if (f->codebooks == NULL) return error(f, VORBIS_outofmem); + memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count); + for (i=0; i < f->codebook_count; ++i) { + uint32 *values; + int ordered, sorted_count; + int total=0; + uint8 *lengths; + Codebook *c = f->codebooks+i; + CHECK(f); + x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); + c->dimensions = (get_bits(f, 8)<<8) + x; + x = get_bits(f, 8); + y = get_bits(f, 8); + c->entries = (get_bits(f, 8)<<16) + (y<<8) + x; + ordered = get_bits(f,1); + c->sparse = ordered ? 0 : get_bits(f,1); + + if (c->dimensions == 0 && c->entries != 0) return error(f, VORBIS_invalid_setup); + + if (c->sparse) + lengths = (uint8 *) setup_temp_malloc(f, c->entries); + else + lengths = c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); + + if (!lengths) return error(f, VORBIS_outofmem); + + if (ordered) { + int current_entry = 0; + int current_length = get_bits(f,5) + 1; + while (current_entry < c->entries) { + int limit = c->entries - current_entry; + int n = get_bits(f, ilog(limit)); + if (current_length >= 32) return error(f, VORBIS_invalid_setup); + if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); } + memset(lengths + current_entry, current_length, n); + current_entry += n; + ++current_length; + } + } else { + for (j=0; j < c->entries; ++j) { + int present = c->sparse ? get_bits(f,1) : 1; + if (present) { + lengths[j] = get_bits(f, 5) + 1; + ++total; + if (lengths[j] == 32) + return error(f, VORBIS_invalid_setup); + } else { + lengths[j] = NO_CODE; + } + } + } + + if (c->sparse && total >= c->entries >> 2) { + // convert sparse items to non-sparse! + if (c->entries > (int) f->setup_temp_memory_required) + f->setup_temp_memory_required = c->entries; + + c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); + if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem); + memcpy(c->codeword_lengths, lengths, c->entries); + setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs! + lengths = c->codeword_lengths; + c->sparse = 0; + } + + // compute the size of the sorted tables + if (c->sparse) { + sorted_count = total; + } else { + sorted_count = 0; + #ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH + for (j=0; j < c->entries; ++j) + if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE) + ++sorted_count; + #endif + } + + c->sorted_entries = sorted_count; + values = NULL; + + CHECK(f); + if (!c->sparse) { + c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries); + if (!c->codewords) return error(f, VORBIS_outofmem); + } else { + unsigned int size; + if (c->sorted_entries) { + c->codeword_lengths = (uint8 *) setup_malloc(f, c->sorted_entries); + if (!c->codeword_lengths) return error(f, VORBIS_outofmem); + c->codewords = (uint32 *) setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries); + if (!c->codewords) return error(f, VORBIS_outofmem); + values = (uint32 *) setup_temp_malloc(f, sizeof(*values) * c->sorted_entries); + if (!values) return error(f, VORBIS_outofmem); + } + size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries; + if (size > f->setup_temp_memory_required) + f->setup_temp_memory_required = size; + } + + if (!compute_codewords(c, lengths, c->entries, values)) { + if (c->sparse) setup_temp_free(f, values, 0); + return error(f, VORBIS_invalid_setup); + } + + if (c->sorted_entries) { + // allocate an extra slot for sentinels + c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1)); + if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem); + // allocate an extra slot at the front so that c->sorted_values[-1] is defined + // so that we can catch that case without an extra if + c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1)); + if (c->sorted_values == NULL) return error(f, VORBIS_outofmem); + ++c->sorted_values; + c->sorted_values[-1] = -1; + compute_sorted_huffman(c, lengths, values); + } + + if (c->sparse) { + setup_temp_free(f, values, sizeof(*values)*c->sorted_entries); + setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries); + setup_temp_free(f, lengths, c->entries); + c->codewords = NULL; + } + + compute_accelerated_huffman(c); + + CHECK(f); + c->lookup_type = get_bits(f, 4); + if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup); + if (c->lookup_type > 0) { + uint16 *mults; + c->minimum_value = float32_unpack(get_bits(f, 32)); + c->delta_value = float32_unpack(get_bits(f, 32)); + c->value_bits = get_bits(f, 4)+1; + c->sequence_p = get_bits(f,1); + if (c->lookup_type == 1) { + int values = lookup1_values(c->entries, c->dimensions); + if (values < 0) return error(f, VORBIS_invalid_setup); + c->lookup_values = (uint32) values; + } else { + c->lookup_values = c->entries * c->dimensions; + } + if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup); + mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values); + if (mults == NULL) return error(f, VORBIS_outofmem); + for (j=0; j < (int) c->lookup_values; ++j) { + int q = get_bits(f, c->value_bits); + if (q == EOP) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); } + mults[j] = q; + } + +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int len, sparse = c->sparse; + float last=0; + // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop + if (sparse) { + if (c->sorted_entries == 0) goto skip; + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions); + } else + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions); + if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } + len = sparse ? c->sorted_entries : c->entries; + for (j=0; j < len; ++j) { + unsigned int z = sparse ? c->sorted_values[j] : j; + unsigned int div=1; + for (k=0; k < c->dimensions; ++k) { + int off = (z / div) % c->lookup_values; + float val = mults[off]*c->delta_value + c->minimum_value + last; + c->multiplicands[j*c->dimensions + k] = val; + if (c->sequence_p) + last = val; + if (k+1 < c->dimensions) { + if (div > UINT_MAX / (unsigned int) c->lookup_values) { + setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); + return error(f, VORBIS_invalid_setup); + } + div *= c->lookup_values; + } + } + } + c->lookup_type = 2; + } + else +#endif + { + float last=0; + CHECK(f); + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); + if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } + for (j=0; j < (int) c->lookup_values; ++j) { + float val = mults[j] * c->delta_value + c->minimum_value + last; + c->multiplicands[j] = val; + if (c->sequence_p) + last = val; + } + } +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + skip:; +#endif + setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values); + + CHECK(f); + } + CHECK(f); + } + + // time domain transfers (notused) + + x = get_bits(f, 6) + 1; + for (i=0; i < x; ++i) { + uint32 z = get_bits(f, 16); + if (z != 0) return error(f, VORBIS_invalid_setup); + } + + // Floors + f->floor_count = get_bits(f, 6)+1; + f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config)); + if (f->floor_config == NULL) return error(f, VORBIS_outofmem); + for (i=0; i < f->floor_count; ++i) { + f->floor_types[i] = get_bits(f, 16); + if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup); + if (f->floor_types[i] == 0) { + Floor0 *g = &f->floor_config[i].floor0; + g->order = get_bits(f,8); + g->rate = get_bits(f,16); + g->bark_map_size = get_bits(f,16); + g->amplitude_bits = get_bits(f,6); + g->amplitude_offset = get_bits(f,8); + g->number_of_books = get_bits(f,4) + 1; + for (j=0; j < g->number_of_books; ++j) + g->book_list[j] = get_bits(f,8); + return error(f, VORBIS_feature_not_supported); + } else { + stbv__floor_ordering p[31*8+2]; + Floor1 *g = &f->floor_config[i].floor1; + int max_class = -1; + g->partitions = get_bits(f, 5); + for (j=0; j < g->partitions; ++j) { + g->partition_class_list[j] = get_bits(f, 4); + if (g->partition_class_list[j] > max_class) + max_class = g->partition_class_list[j]; + } + for (j=0; j <= max_class; ++j) { + g->class_dimensions[j] = get_bits(f, 3)+1; + g->class_subclasses[j] = get_bits(f, 2); + if (g->class_subclasses[j]) { + g->class_masterbooks[j] = get_bits(f, 8); + if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + for (k=0; k < 1 << g->class_subclasses[j]; ++k) { + g->subclass_books[j][k] = (int16)get_bits(f,8)-1; + if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + } + g->floor1_multiplier = get_bits(f,2)+1; + g->rangebits = get_bits(f,4); + g->Xlist[0] = 0; + g->Xlist[1] = 1 << g->rangebits; + g->values = 2; + for (j=0; j < g->partitions; ++j) { + int c = g->partition_class_list[j]; + for (k=0; k < g->class_dimensions[c]; ++k) { + g->Xlist[g->values] = get_bits(f, g->rangebits); + ++g->values; + } + } + // precompute the sorting + for (j=0; j < g->values; ++j) { + p[j].x = g->Xlist[j]; + p[j].id = j; + } + qsort(p, g->values, sizeof(p[0]), point_compare); + for (j=0; j < g->values-1; ++j) + if (p[j].x == p[j+1].x) + return error(f, VORBIS_invalid_setup); + for (j=0; j < g->values; ++j) + g->sorted_order[j] = (uint8) p[j].id; + // precompute the neighbors + for (j=2; j < g->values; ++j) { + int low = 0,hi = 0; + neighbors(g->Xlist, j, &low,&hi); + g->neighbors[j][0] = low; + g->neighbors[j][1] = hi; + } + + if (g->values > longest_floorlist) + longest_floorlist = g->values; + } + } + + // Residue + f->residue_count = get_bits(f, 6)+1; + f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(f->residue_config[0])); + if (f->residue_config == NULL) return error(f, VORBIS_outofmem); + memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0])); + for (i=0; i < f->residue_count; ++i) { + uint8 residue_cascade[64]; + Residue *r = f->residue_config+i; + f->residue_types[i] = get_bits(f, 16); + if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup); + r->begin = get_bits(f, 24); + r->end = get_bits(f, 24); + if (r->end < r->begin) return error(f, VORBIS_invalid_setup); + r->part_size = get_bits(f,24)+1; + r->classifications = get_bits(f,6)+1; + r->classbook = get_bits(f,8); + if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup); + for (j=0; j < r->classifications; ++j) { + uint8 high_bits=0; + uint8 low_bits=get_bits(f,3); + if (get_bits(f,1)) + high_bits = get_bits(f,5); + residue_cascade[j] = high_bits*8 + low_bits; + } + r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications); + if (r->residue_books == NULL) return error(f, VORBIS_outofmem); + for (j=0; j < r->classifications; ++j) { + for (k=0; k < 8; ++k) { + if (residue_cascade[j] & (1 << k)) { + r->residue_books[j][k] = get_bits(f, 8); + if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } else { + r->residue_books[j][k] = -1; + } + } + } + // precompute the classifications[] array to avoid inner-loop mod/divide + // call it 'classdata' since we already have r->classifications + r->classdata = (uint8 **) setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); + if (!r->classdata) return error(f, VORBIS_outofmem); + memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); + for (j=0; j < f->codebooks[r->classbook].entries; ++j) { + int classwords = f->codebooks[r->classbook].dimensions; + int temp = j; + r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords); + if (r->classdata[j] == NULL) return error(f, VORBIS_outofmem); + for (k=classwords-1; k >= 0; --k) { + r->classdata[j][k] = temp % r->classifications; + temp /= r->classifications; + } + } + } + + f->mapping_count = get_bits(f,6)+1; + f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping)); + if (f->mapping == NULL) return error(f, VORBIS_outofmem); + memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping)); + for (i=0; i < f->mapping_count; ++i) { + Mapping *m = f->mapping + i; + int mapping_type = get_bits(f,16); + if (mapping_type != 0) return error(f, VORBIS_invalid_setup); + m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan)); + if (m->chan == NULL) return error(f, VORBIS_outofmem); + if (get_bits(f,1)) + m->submaps = get_bits(f,4)+1; + else + m->submaps = 1; + if (m->submaps > max_submaps) + max_submaps = m->submaps; + if (get_bits(f,1)) { + m->coupling_steps = get_bits(f,8)+1; + if (m->coupling_steps > f->channels) return error(f, VORBIS_invalid_setup); + for (k=0; k < m->coupling_steps; ++k) { + m->chan[k].magnitude = get_bits(f, ilog(f->channels-1)); + m->chan[k].angle = get_bits(f, ilog(f->channels-1)); + if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup); + if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup); + if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup); + } + } else + m->coupling_steps = 0; + + // reserved field + if (get_bits(f,2)) return error(f, VORBIS_invalid_setup); + if (m->submaps > 1) { + for (j=0; j < f->channels; ++j) { + m->chan[j].mux = get_bits(f, 4); + if (m->chan[j].mux >= m->submaps) return error(f, VORBIS_invalid_setup); + } + } else + // @SPECIFICATION: this case is missing from the spec + for (j=0; j < f->channels; ++j) + m->chan[j].mux = 0; + + for (j=0; j < m->submaps; ++j) { + get_bits(f,8); // discard + m->submap_floor[j] = get_bits(f,8); + m->submap_residue[j] = get_bits(f,8); + if (m->submap_floor[j] >= f->floor_count) return error(f, VORBIS_invalid_setup); + if (m->submap_residue[j] >= f->residue_count) return error(f, VORBIS_invalid_setup); + } + } + + // Modes + f->mode_count = get_bits(f, 6)+1; + for (i=0; i < f->mode_count; ++i) { + Mode *m = f->mode_config+i; + m->blockflag = get_bits(f,1); + m->windowtype = get_bits(f,16); + m->transformtype = get_bits(f,16); + m->mapping = get_bits(f,8); + if (m->windowtype != 0) return error(f, VORBIS_invalid_setup); + if (m->transformtype != 0) return error(f, VORBIS_invalid_setup); + if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup); + } + + flush_packet(f); + + f->previous_length = 0; + + for (i=0; i < f->channels; ++i) { + f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1); + f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); + f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist); + if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem); + memset(f->channel_buffers[i], 0, sizeof(float) * f->blocksize_1); + #ifdef STB_VORBIS_NO_DEFER_FLOOR + f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); + if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem); + #endif + } + + if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE; + if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE; + f->blocksize[0] = f->blocksize_0; + f->blocksize[1] = f->blocksize_1; + +#ifdef STB_VORBIS_DIVIDE_TABLE + if (integer_divide_table[1][1]==0) + for (i=0; i < DIVTAB_NUMER; ++i) + for (j=1; j < DIVTAB_DENOM; ++j) + integer_divide_table[i][j] = i / j; +#endif + + // compute how much temporary memory is needed + + // 1. + { + uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1); + uint32 classify_mem; + int i,max_part_read=0; + for (i=0; i < f->residue_count; ++i) { + Residue *r = f->residue_config + i; + unsigned int actual_size = f->blocksize_1 / 2; + unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size; + unsigned int limit_r_end = r->end < actual_size ? r->end : actual_size; + int n_read = limit_r_end - limit_r_begin; + int part_read = n_read / r->part_size; + if (part_read > max_part_read) + max_part_read = part_read; + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8 *)); + #else + classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); + #endif + + // maximum reasonable partition size is f->blocksize_1 + + f->temp_memory_required = classify_mem; + if (imdct_mem > f->temp_memory_required) + f->temp_memory_required = imdct_mem; + } + + + if (f->alloc.alloc_buffer) { + assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes); + // check if there's enough temp memory so we don't error later + if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset) + return error(f, VORBIS_outofmem); + } + + // @TODO: stb_vorbis_seek_start expects first_audio_page_offset to point to a page + // without PAGEFLAG_continued_packet, so this either points to the first page, or + // the page after the end of the headers. It might be cleaner to point to a page + // in the middle of the headers, when that's the page where the first audio packet + // starts, but we'd have to also correctly skip the end of any continued packet in + // stb_vorbis_seek_start. + if (f->next_seg == -1) { + f->first_audio_page_offset = stb_vorbis_get_file_offset(f); + } else { + f->first_audio_page_offset = 0; + } + + return TRUE; +} + +static void vorbis_deinit(stb_vorbis *p) +{ + int i,j; + + setup_free(p, p->vendor); + for (i=0; i < p->comment_list_length; ++i) { + setup_free(p, p->comment_list[i]); + } + setup_free(p, p->comment_list); + + if (p->residue_config) { + for (i=0; i < p->residue_count; ++i) { + Residue *r = p->residue_config+i; + if (r->classdata) { + for (j=0; j < p->codebooks[r->classbook].entries; ++j) + setup_free(p, r->classdata[j]); + setup_free(p, r->classdata); + } + setup_free(p, r->residue_books); + } + } + + if (p->codebooks) { + CHECK(p); + for (i=0; i < p->codebook_count; ++i) { + Codebook *c = p->codebooks + i; + setup_free(p, c->codeword_lengths); + setup_free(p, c->multiplicands); + setup_free(p, c->codewords); + setup_free(p, c->sorted_codewords); + // c->sorted_values[-1] is the first entry in the array + setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL); + } + setup_free(p, p->codebooks); + } + setup_free(p, p->floor_config); + setup_free(p, p->residue_config); + if (p->mapping) { + for (i=0; i < p->mapping_count; ++i) + setup_free(p, p->mapping[i].chan); + setup_free(p, p->mapping); + } + CHECK(p); + for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) { + setup_free(p, p->channel_buffers[i]); + setup_free(p, p->previous_window[i]); + #ifdef STB_VORBIS_NO_DEFER_FLOOR + setup_free(p, p->floor_buffers[i]); + #endif + setup_free(p, p->finalY[i]); + } + for (i=0; i < 2; ++i) { + setup_free(p, p->A[i]); + setup_free(p, p->B[i]); + setup_free(p, p->C[i]); + setup_free(p, p->window[i]); + setup_free(p, p->bit_reverse[i]); + } + #ifndef STB_VORBIS_NO_STDIO + if (p->close_on_free) fclose(p->f); + #endif +} + +void stb_vorbis_close(stb_vorbis *p) +{ + if (p == NULL) return; + vorbis_deinit(p); + setup_free(p,p); +} + +static void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z) +{ + memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start + if (z) { + p->alloc = *z; + p->alloc.alloc_buffer_length_in_bytes &= ~7; + p->temp_offset = p->alloc.alloc_buffer_length_in_bytes; + } + p->eof = 0; + p->error = VORBIS__no_error; + p->stream = NULL; + p->codebooks = NULL; + p->page_crc_tests = -1; + #ifndef STB_VORBIS_NO_STDIO + p->close_on_free = FALSE; + p->f = NULL; + #endif +} + +int stb_vorbis_get_sample_offset(stb_vorbis *f) +{ + if (f->current_loc_valid) + return f->current_loc; + else + return -1; +} + +stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f) +{ + stb_vorbis_info d; + d.channels = f->channels; + d.sample_rate = f->sample_rate; + d.setup_memory_required = f->setup_memory_required; + d.setup_temp_memory_required = f->setup_temp_memory_required; + d.temp_memory_required = f->temp_memory_required; + d.max_frame_size = f->blocksize_1 >> 1; + return d; +} + +stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f) +{ + stb_vorbis_comment d; + d.vendor = f->vendor; + d.comment_list_length = f->comment_list_length; + d.comment_list = f->comment_list; + return d; +} + +int stb_vorbis_get_error(stb_vorbis *f) +{ + int e = f->error; + f->error = VORBIS__no_error; + return e; +} + +static stb_vorbis * vorbis_alloc(stb_vorbis *f) +{ + stb_vorbis *p = (stb_vorbis *) setup_malloc(f, sizeof(*p)); + return p; +} + +#ifndef STB_VORBIS_NO_PUSHDATA_API + +void stb_vorbis_flush_pushdata(stb_vorbis *f) +{ + f->previous_length = 0; + f->page_crc_tests = 0; + f->discard_samples_deferred = 0; + f->current_loc_valid = FALSE; + f->first_decode = FALSE; + f->samples_output = 0; + f->channel_buffer_start = 0; + f->channel_buffer_end = 0; +} + +static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len) +{ + int i,n; + for (i=0; i < f->page_crc_tests; ++i) + f->scan[i].bytes_done = 0; + + // if we have room for more scans, search for them first, because + // they may cause us to stop early if their header is incomplete + if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) { + if (data_len < 4) return 0; + data_len -= 3; // need to look for 4-byte sequence, so don't miss + // one that straddles a boundary + for (i=0; i < data_len; ++i) { + if (data[i] == 0x4f) { + if (0==memcmp(data+i, ogg_page_header, 4)) { + int j,len; + uint32 crc; + // make sure we have the whole page header + if (i+26 >= data_len || i+27+data[i+26] >= data_len) { + // only read up to this page start, so hopefully we'll + // have the whole page header start next time + data_len = i; + break; + } + // ok, we have it all; compute the length of the page + len = 27 + data[i+26]; + for (j=0; j < data[i+26]; ++j) + len += data[i+27+j]; + // scan everything up to the embedded crc (which we must 0) + crc = 0; + for (j=0; j < 22; ++j) + crc = crc32_update(crc, data[i+j]); + // now process 4 0-bytes + for ( ; j < 26; ++j) + crc = crc32_update(crc, 0); + // len is the total number of bytes we need to scan + n = f->page_crc_tests++; + f->scan[n].bytes_left = len-j; + f->scan[n].crc_so_far = crc; + f->scan[n].goal_crc = data[i+22] + (data[i+23] << 8) + (data[i+24]<<16) + (data[i+25]<<24); + // if the last frame on a page is continued to the next, then + // we can't recover the sample_loc immediately + if (data[i+27+data[i+26]-1] == 255) + f->scan[n].sample_loc = ~0; + else + f->scan[n].sample_loc = data[i+6] + (data[i+7] << 8) + (data[i+ 8]<<16) + (data[i+ 9]<<24); + f->scan[n].bytes_done = i+j; + if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT) + break; + // keep going if we still have room for more + } + } + } + } + + for (i=0; i < f->page_crc_tests;) { + uint32 crc; + int j; + int n = f->scan[i].bytes_done; + int m = f->scan[i].bytes_left; + if (m > data_len - n) m = data_len - n; + // m is the bytes to scan in the current chunk + crc = f->scan[i].crc_so_far; + for (j=0; j < m; ++j) + crc = crc32_update(crc, data[n+j]); + f->scan[i].bytes_left -= m; + f->scan[i].crc_so_far = crc; + if (f->scan[i].bytes_left == 0) { + // does it match? + if (f->scan[i].crc_so_far == f->scan[i].goal_crc) { + // Houston, we have page + data_len = n+m; // consumption amount is wherever that scan ended + f->page_crc_tests = -1; // drop out of page scan mode + f->previous_length = 0; // decode-but-don't-output one frame + f->next_seg = -1; // start a new page + f->current_loc = f->scan[i].sample_loc; // set the current sample location + // to the amount we'd have decoded had we decoded this page + f->current_loc_valid = f->current_loc != ~0U; + return data_len; + } + // delete entry + f->scan[i] = f->scan[--f->page_crc_tests]; + } else { + ++i; + } + } + + return data_len; +} + +// return value: number of bytes we used +int stb_vorbis_decode_frame_pushdata( + stb_vorbis *f, // the file we're decoding + const uint8 *data, int data_len, // the memory available for decoding + int *channels, // place to write number of float * buffers + float ***output, // place to write float ** array of float * buffers + int *samples // place to write number of output samples + ) +{ + int i; + int len,right,left; + + if (!IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + if (f->page_crc_tests >= 0) { + *samples = 0; + return vorbis_search_for_page_pushdata(f, (uint8 *) data, data_len); + } + + f->stream = (uint8 *) data; + f->stream_end = (uint8 *) data + data_len; + f->error = VORBIS__no_error; + + // check that we have the entire packet in memory + if (!is_whole_packet_present(f)) { + *samples = 0; + return 0; + } + + if (!vorbis_decode_packet(f, &len, &left, &right)) { + // save the actual error we encountered + enum STBVorbisError error = f->error; + if (error == VORBIS_bad_packet_type) { + // flush and resynch + f->error = VORBIS__no_error; + while (get8_packet(f) != EOP) + if (f->eof) break; + *samples = 0; + return (int) (f->stream - data); + } + if (error == VORBIS_continued_packet_flag_invalid) { + if (f->previous_length == 0) { + // we may be resynching, in which case it's ok to hit one + // of these; just discard the packet + f->error = VORBIS__no_error; + while (get8_packet(f) != EOP) + if (f->eof) break; + *samples = 0; + return (int) (f->stream - data); + } + } + // if we get an error while parsing, what to do? + // well, it DEFINITELY won't work to continue from where we are! + stb_vorbis_flush_pushdata(f); + // restore the error that actually made us bail + f->error = error; + *samples = 0; + return 1; + } + + // success! + len = vorbis_finish_frame(f, len, left, right); + for (i=0; i < f->channels; ++i) + f->outputs[i] = f->channel_buffers[i] + left; + + if (channels) *channels = f->channels; + *samples = len; + *output = f->outputs; + return (int) (f->stream - data); +} + +stb_vorbis *stb_vorbis_open_pushdata( + const unsigned char *data, int data_len, // the memory available for decoding + int *data_used, // only defined if result is not NULL + int *error, const stb_vorbis_alloc *alloc) +{ + stb_vorbis *f, p; + vorbis_init(&p, alloc); + p.stream = (uint8 *) data; + p.stream_end = (uint8 *) data + data_len; + p.push_mode = TRUE; + if (!start_decoder(&p)) { + if (p.eof) + *error = VORBIS_need_more_data; + else + *error = p.error; + vorbis_deinit(&p); + return NULL; + } + f = vorbis_alloc(&p); + if (f) { + *f = p; + *data_used = (int) (f->stream - data); + *error = 0; + return f; + } else { + vorbis_deinit(&p); + return NULL; + } +} +#endif // STB_VORBIS_NO_PUSHDATA_API + +unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) +{ + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (f->push_mode) return 0; + #endif + if (USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start); + #ifndef STB_VORBIS_NO_STDIO + return (unsigned int) (ftell(f->f) - f->f_start); + #endif +} + +#ifndef STB_VORBIS_NO_PULLDATA_API +// +// DATA-PULLING API +// + +static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) +{ + for(;;) { + int n; + if (f->eof) return 0; + n = get8(f); + if (n == 0x4f) { // page header candidate + unsigned int retry_loc = stb_vorbis_get_file_offset(f); + int i; + // check if we're off the end of a file_section stream + if (retry_loc - 25 > f->stream_len) + return 0; + // check the rest of the header + for (i=1; i < 4; ++i) + if (get8(f) != ogg_page_header[i]) + break; + if (f->eof) return 0; + if (i == 4) { + uint8 header[27]; + uint32 i, crc, goal, len; + for (i=0; i < 4; ++i) + header[i] = ogg_page_header[i]; + for (; i < 27; ++i) + header[i] = get8(f); + if (f->eof) return 0; + if (header[4] != 0) goto invalid; + goal = header[22] + (header[23] << 8) + (header[24]<<16) + ((uint32)header[25]<<24); + for (i=22; i < 26; ++i) + header[i] = 0; + crc = 0; + for (i=0; i < 27; ++i) + crc = crc32_update(crc, header[i]); + len = 0; + for (i=0; i < header[26]; ++i) { + int s = get8(f); + crc = crc32_update(crc, s); + len += s; + } + if (len && f->eof) return 0; + for (i=0; i < len; ++i) + crc = crc32_update(crc, get8(f)); + // finished parsing probable page + if (crc == goal) { + // we could now check that it's either got the last + // page flag set, OR it's followed by the capture + // pattern, but I guess TECHNICALLY you could have + // a file with garbage between each ogg page and recover + // from it automatically? So even though that paranoia + // might decrease the chance of an invalid decode by + // another 2^32, not worth it since it would hose those + // invalid-but-useful files? + if (end) + *end = stb_vorbis_get_file_offset(f); + if (last) { + if (header[5] & 0x04) + *last = 1; + else + *last = 0; + } + set_file_offset(f, retry_loc-1); + return 1; + } + } + invalid: + // not a valid page, so rewind and look for next one + set_file_offset(f, retry_loc); + } + } +} + + +#define SAMPLE_unknown 0xffffffff + +// seeking is implemented with a binary search, which narrows down the range to +// 64K, before using a linear search (because finding the synchronization +// pattern can be expensive, and the chance we'd find the end page again is +// relatively high for small ranges) +// +// two initial interpolation-style probes are used at the start of the search +// to try to bound either side of the binary search sensibly, while still +// working in O(log n) time if they fail. + +static int get_seek_page_info(stb_vorbis *f, ProbedPage *z) +{ + uint8 header[27], lacing[255]; + int i,len; + + // record where the page starts + z->page_start = stb_vorbis_get_file_offset(f); + + // parse the header + getn(f, header, 27); + if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S') + return 0; + getn(f, lacing, header[26]); + + // determine the length of the payload + len = 0; + for (i=0; i < header[26]; ++i) + len += lacing[i]; + + // this implies where the page ends + z->page_end = z->page_start + 27 + header[26] + len; + + // read the last-decoded sample out of the data + z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24); + + // restore file state to where we were + set_file_offset(f, z->page_start); + return 1; +} + +// rarely used function to seek back to the preceding page while finding the +// start of a packet +static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset) +{ + unsigned int previous_safe, end; + + // now we want to seek back 64K from the limit + if (limit_offset >= 65536 && limit_offset-65536 >= f->first_audio_page_offset) + previous_safe = limit_offset - 65536; + else + previous_safe = f->first_audio_page_offset; + + set_file_offset(f, previous_safe); + + while (vorbis_find_page(f, &end, NULL)) { + if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset) + return 1; + set_file_offset(f, end); + } + + return 0; +} + +// implements the search logic for finding a page and starting decoding. if +// the function succeeds, current_loc_valid will be true and current_loc will +// be less than or equal to the provided sample number (the closer the +// better). +static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number) +{ + ProbedPage left, right, mid; + int i, start_seg_with_known_loc, end_pos, page_start; + uint32 delta, stream_length, padding, last_sample_limit; + double offset = 0.0, bytes_per_sample = 0.0; + int probe = 0; + + // find the last page and validate the target sample + stream_length = stb_vorbis_stream_length_in_samples(f); + if (stream_length == 0) return error(f, VORBIS_seek_without_length); + if (sample_number > stream_length) return error(f, VORBIS_seek_invalid); + + // this is the maximum difference between the window-center (which is the + // actual granule position value), and the right-start (which the spec + // indicates should be the granule position (give or take one)). + padding = ((f->blocksize_1 - f->blocksize_0) >> 2); + if (sample_number < padding) + last_sample_limit = 0; + else + last_sample_limit = sample_number - padding; + + left = f->p_first; + while (left.last_decoded_sample == ~0U) { + // (untested) the first page does not have a 'last_decoded_sample' + set_file_offset(f, left.page_end); + if (!get_seek_page_info(f, &left)) goto error; + } + + right = f->p_last; + assert(right.last_decoded_sample != ~0U); + + // starting from the start is handled differently + if (last_sample_limit <= left.last_decoded_sample) { + if (stb_vorbis_seek_start(f)) { + if (f->current_loc > sample_number) + return error(f, VORBIS_seek_failed); + return 1; + } + return 0; + } + + while (left.page_end != right.page_start) { + assert(left.page_end < right.page_start); + // search range in bytes + delta = right.page_start - left.page_end; + if (delta <= 65536) { + // there's only 64K left to search - handle it linearly + set_file_offset(f, left.page_end); + } else { + if (probe < 2) { + if (probe == 0) { + // first probe (interpolate) + double data_bytes = right.page_end - left.page_start; + bytes_per_sample = data_bytes / right.last_decoded_sample; + offset = left.page_start + bytes_per_sample * (last_sample_limit - left.last_decoded_sample); + } else { + // second probe (try to bound the other side) + double error = ((double) last_sample_limit - mid.last_decoded_sample) * bytes_per_sample; + if (error >= 0 && error < 8000) error = 8000; + if (error < 0 && error > -8000) error = -8000; + offset += error * 2; + } + + // ensure the offset is valid + if (offset < left.page_end) + offset = left.page_end; + if (offset > right.page_start - 65536) + offset = right.page_start - 65536; + + set_file_offset(f, (unsigned int) offset); + } else { + // binary search for large ranges (offset by 32K to ensure + // we don't hit the right page) + set_file_offset(f, left.page_end + (delta / 2) - 32768); + } + + if (!vorbis_find_page(f, NULL, NULL)) goto error; + } + + for (;;) { + if (!get_seek_page_info(f, &mid)) goto error; + if (mid.last_decoded_sample != ~0U) break; + // (untested) no frames end on this page + set_file_offset(f, mid.page_end); + assert(mid.page_start < right.page_start); + } + + // if we've just found the last page again then we're in a tricky file, + // and we're close enough (if it wasn't an interpolation probe). + if (mid.page_start == right.page_start) { + if (probe >= 2 || delta <= 65536) + break; + } else { + if (last_sample_limit < mid.last_decoded_sample) + right = mid; + else + left = mid; + } + + ++probe; + } + + // seek back to start of the last packet + page_start = left.page_start; + set_file_offset(f, page_start); + if (!start_page(f)) return error(f, VORBIS_seek_failed); + end_pos = f->end_seg_with_known_loc; + assert(end_pos >= 0); + + for (;;) { + for (i = end_pos; i > 0; --i) + if (f->segments[i-1] != 255) + break; + + start_seg_with_known_loc = i; + + if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet)) + break; + + // (untested) the final packet begins on an earlier page + if (!go_to_page_before(f, page_start)) + goto error; + + page_start = stb_vorbis_get_file_offset(f); + if (!start_page(f)) goto error; + end_pos = f->segment_count - 1; + } + + // prepare to start decoding + f->current_loc_valid = FALSE; + f->last_seg = FALSE; + f->valid_bits = 0; + f->packet_bytes = 0; + f->bytes_in_seg = 0; + f->previous_length = 0; + f->next_seg = start_seg_with_known_loc; + + for (i = 0; i < start_seg_with_known_loc; i++) + skip(f, f->segments[i]); + + // start decoding (optimizable - this frame is generally discarded) + if (!vorbis_pump_first_frame(f)) + return 0; + if (f->current_loc > sample_number) + return error(f, VORBIS_seek_failed); + return 1; + +error: + // try to restore the file to a valid state + stb_vorbis_seek_start(f); + return error(f, VORBIS_seek_failed); +} + +// the same as vorbis_decode_initial, but without advancing +static int peek_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) +{ + int bits_read, bytes_read; + + if (!vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode)) + return 0; + + // either 1 or 2 bytes were read, figure out which so we can rewind + bits_read = 1 + ilog(f->mode_count-1); + if (f->mode_config[*mode].blockflag) + bits_read += 2; + bytes_read = (bits_read + 7) / 8; + + f->bytes_in_seg += bytes_read; + f->packet_bytes -= bytes_read; + skip(f, -bytes_read); + if (f->next_seg == -1) + f->next_seg = f->segment_count - 1; + else + f->next_seg--; + f->valid_bits = 0; + + return 1; +} + +int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) +{ + uint32 max_frame_samples; + + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + // fast page-level search + if (!seek_to_sample_coarse(f, sample_number)) + return 0; + + assert(f->current_loc_valid); + assert(f->current_loc <= sample_number); + + // linear search for the relevant packet + max_frame_samples = (f->blocksize_1*3 - f->blocksize_0) >> 2; + while (f->current_loc < sample_number) { + int left_start, left_end, right_start, right_end, mode, frame_samples; + if (!peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) + return error(f, VORBIS_seek_failed); + // calculate the number of samples returned by the next frame + frame_samples = right_start - left_start; + if (f->current_loc + frame_samples > sample_number) { + return 1; // the next frame will contain the sample + } else if (f->current_loc + frame_samples + max_frame_samples > sample_number) { + // there's a chance the frame after this could contain the sample + vorbis_pump_first_frame(f); + } else { + // this frame is too early to be relevant + f->current_loc += frame_samples; + f->previous_length = 0; + maybe_start_packet(f); + flush_packet(f); + } + } + // the next frame should start with the sample + if (f->current_loc != sample_number) return error(f, VORBIS_seek_failed); + return 1; +} + +int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) +{ + if (!stb_vorbis_seek_frame(f, sample_number)) + return 0; + + if (sample_number != f->current_loc) { + int n; + uint32 frame_start = f->current_loc; + stb_vorbis_get_frame_float(f, &n, NULL); + assert(sample_number > frame_start); + assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end); + f->channel_buffer_start += (sample_number - frame_start); + } + + return 1; +} + +int stb_vorbis_seek_start(stb_vorbis *f) +{ + if (IS_PUSH_MODE(f)) { return error(f, VORBIS_invalid_api_mixing); } + set_file_offset(f, f->first_audio_page_offset); + f->previous_length = 0; + f->first_decode = TRUE; + f->next_seg = -1; + return vorbis_pump_first_frame(f); +} + +unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) +{ + unsigned int restore_offset, previous_safe; + unsigned int end, last_page_loc; + + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + if (!f->total_samples) { + unsigned int last; + uint32 lo,hi; + char header[6]; + + // first, store the current decode position so we can restore it + restore_offset = stb_vorbis_get_file_offset(f); + + // now we want to seek back 64K from the end (the last page must + // be at most a little less than 64K, but let's allow a little slop) + if (f->stream_len >= 65536 && f->stream_len-65536 >= f->first_audio_page_offset) + previous_safe = f->stream_len - 65536; + else + previous_safe = f->first_audio_page_offset; + + set_file_offset(f, previous_safe); + // previous_safe is now our candidate 'earliest known place that seeking + // to will lead to the final page' + + if (!vorbis_find_page(f, &end, &last)) { + // if we can't find a page, we're hosed! + f->error = VORBIS_cant_find_last_page; + f->total_samples = 0xffffffff; + goto done; + } + + // check if there are more pages + last_page_loc = stb_vorbis_get_file_offset(f); + + // stop when the last_page flag is set, not when we reach eof; + // this allows us to stop short of a 'file_section' end without + // explicitly checking the length of the section + while (!last) { + set_file_offset(f, end); + if (!vorbis_find_page(f, &end, &last)) { + // the last page we found didn't have the 'last page' flag + // set. whoops! + break; + } + //previous_safe = last_page_loc+1; // NOTE: not used after this point, but note for debugging + last_page_loc = stb_vorbis_get_file_offset(f); + } + + set_file_offset(f, last_page_loc); + + // parse the header + getn(f, (unsigned char *)header, 6); + // extract the absolute granule position + lo = get32(f); + hi = get32(f); + if (lo == 0xffffffff && hi == 0xffffffff) { + f->error = VORBIS_cant_find_last_page; + f->total_samples = SAMPLE_unknown; + goto done; + } + if (hi) + lo = 0xfffffffe; // saturate + f->total_samples = lo; + + f->p_last.page_start = last_page_loc; + f->p_last.page_end = end; + f->p_last.last_decoded_sample = lo; + + done: + set_file_offset(f, restore_offset); + } + return f->total_samples == SAMPLE_unknown ? 0 : f->total_samples; +} + +float stb_vorbis_stream_length_in_seconds(stb_vorbis *f) +{ + return stb_vorbis_stream_length_in_samples(f) / (float) f->sample_rate; +} + + + +int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output) +{ + int len, right,left,i; + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + if (!vorbis_decode_packet(f, &len, &left, &right)) { + f->channel_buffer_start = f->channel_buffer_end = 0; + return 0; + } + + len = vorbis_finish_frame(f, len, left, right); + for (i=0; i < f->channels; ++i) + f->outputs[i] = f->channel_buffers[i] + left; + + f->channel_buffer_start = left; + f->channel_buffer_end = left+len; + + if (channels) *channels = f->channels; + if (output) *output = f->outputs; + return len; +} + +#ifndef STB_VORBIS_NO_STDIO + +stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length) +{ + stb_vorbis *f, p; + vorbis_init(&p, alloc); + p.f = file; + p.f_start = (uint32) ftell(file); + p.stream_len = length; + p.close_on_free = close_on_free; + if (start_decoder(&p)) { + f = vorbis_alloc(&p); + if (f) { + *f = p; + vorbis_pump_first_frame(f); + return f; + } + } + if (error) *error = p.error; + vorbis_deinit(&p); + return NULL; +} + +stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc) +{ + unsigned int len, start; + start = (unsigned int) ftell(file); + fseek(file, 0, SEEK_END); + len = (unsigned int) (ftell(file) - start); + fseek(file, start, SEEK_SET); + return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); +} + +stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc) +{ + FILE *f; +#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__) + if (0 != fopen_s(&f, filename, "rb")) + f = NULL; +#else + f = fopen(filename, "rb"); +#endif + if (f) + return stb_vorbis_open_file(f, TRUE, error, alloc); + if (error) *error = VORBIS_file_open_failure; + return NULL; +} +#endif // STB_VORBIS_NO_STDIO + +stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc) +{ + stb_vorbis *f, p; + if (!data) { + if (error) *error = VORBIS_unexpected_eof; + return NULL; + } + vorbis_init(&p, alloc); + p.stream = (uint8 *) data; + p.stream_end = (uint8 *) data + len; + p.stream_start = (uint8 *) p.stream; + p.stream_len = len; + p.push_mode = FALSE; + if (start_decoder(&p)) { + f = vorbis_alloc(&p); + if (f) { + *f = p; + vorbis_pump_first_frame(f); + if (error) *error = VORBIS__no_error; + return f; + } + } + if (error) *error = p.error; + vorbis_deinit(&p); + return NULL; +} + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +#define PLAYBACK_MONO 1 +#define PLAYBACK_LEFT 2 +#define PLAYBACK_RIGHT 4 + +#define L (PLAYBACK_LEFT | PLAYBACK_MONO) +#define C (PLAYBACK_LEFT | PLAYBACK_RIGHT | PLAYBACK_MONO) +#define R (PLAYBACK_RIGHT | PLAYBACK_MONO) + +static int8 channel_position[7][6] = +{ + { 0 }, + { C }, + { L, R }, + { L, C, R }, + { L, R, L, R }, + { L, C, R, L, R }, + { L, C, R, L, R, C }, +}; + + +#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT + typedef union { + float f; + int i; + } float_conv; + typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4]; + #define FASTDEF(x) float_conv x + // add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round + #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT)) + #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22)) + #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s)) + #define check_endianness() +#else + #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s)))) + #define check_endianness() + #define FASTDEF(x) +#endif + +static void copy_samples(short *dest, float *src, int len) +{ + int i; + check_endianness(); + for (i=0; i < len; ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + dest[i] = v; + } +} + +static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len) +{ + #define STB_BUFFER_SIZE 32 + float buffer[STB_BUFFER_SIZE]; + int i,j,o,n = STB_BUFFER_SIZE; + check_endianness(); + for (o = 0; o < len; o += STB_BUFFER_SIZE) { + memset(buffer, 0, sizeof(buffer)); + if (o + n > len) n = len - o; + for (j=0; j < num_c; ++j) { + if (channel_position[num_c][j] & mask) { + for (i=0; i < n; ++i) + buffer[i] += data[j][d_offset+o+i]; + } + } + for (i=0; i < n; ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + output[o+i] = v; + } + } + #undef STB_BUFFER_SIZE +} + +static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len) +{ + #define STB_BUFFER_SIZE 32 + float buffer[STB_BUFFER_SIZE]; + int i,j,o,n = STB_BUFFER_SIZE >> 1; + // o is the offset in the source data + check_endianness(); + for (o = 0; o < len; o += STB_BUFFER_SIZE >> 1) { + // o2 is the offset in the output data + int o2 = o << 1; + memset(buffer, 0, sizeof(buffer)); + if (o + n > len) n = len - o; + for (j=0; j < num_c; ++j) { + int m = channel_position[num_c][j] & (PLAYBACK_LEFT | PLAYBACK_RIGHT); + if (m == (PLAYBACK_LEFT | PLAYBACK_RIGHT)) { + for (i=0; i < n; ++i) { + buffer[i*2+0] += data[j][d_offset+o+i]; + buffer[i*2+1] += data[j][d_offset+o+i]; + } + } else if (m == PLAYBACK_LEFT) { + for (i=0; i < n; ++i) { + buffer[i*2+0] += data[j][d_offset+o+i]; + } + } else if (m == PLAYBACK_RIGHT) { + for (i=0; i < n; ++i) { + buffer[i*2+1] += data[j][d_offset+o+i]; + } + } + } + for (i=0; i < (n<<1); ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + output[o2+i] = v; + } + } + #undef STB_BUFFER_SIZE +} + +static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples) +{ + int i; + if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { + static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} }; + for (i=0; i < buf_c; ++i) + compute_samples(channel_selector[buf_c][i], buffer[i]+b_offset, data_c, data, d_offset, samples); + } else { + int limit = buf_c < data_c ? buf_c : data_c; + for (i=0; i < limit; ++i) + copy_samples(buffer[i]+b_offset, data[i]+d_offset, samples); + for ( ; i < buf_c; ++i) + memset(buffer[i]+b_offset, 0, sizeof(short) * samples); + } +} + +int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples) +{ + float **output = NULL; + int len = stb_vorbis_get_frame_float(f, NULL, &output); + if (len > num_samples) len = num_samples; + if (len) + convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len); + return len; +} + +static void convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len) +{ + int i; + check_endianness(); + if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { + assert(buf_c == 2); + for (i=0; i < buf_c; ++i) + compute_stereo_samples(buffer, data_c, data, d_offset, len); + } else { + int limit = buf_c < data_c ? buf_c : data_c; + int j; + for (j=0; j < len; ++j) { + for (i=0; i < limit; ++i) { + FASTDEF(temp); + float f = data[i][d_offset+j]; + int v = FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + *buffer++ = v; + } + for ( ; i < buf_c; ++i) + *buffer++ = 0; + } + } +} + +int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts) +{ + float **output; + int len; + if (num_c == 1) return stb_vorbis_get_frame_short(f,num_c,&buffer, num_shorts); + len = stb_vorbis_get_frame_float(f, NULL, &output); + if (len) { + if (len*num_c > num_shorts) len = num_shorts / num_c; + convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len); + } + return len; +} + +int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts) +{ + float **outputs; + int len = num_shorts / channels; + int n=0; + while (n < len) { + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + if (k) + convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, k); + buffer += k*channels; + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; +} + +int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len) +{ + float **outputs; + int n=0; + while (n < len) { + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + if (k) + convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k); + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; +} + +#ifndef STB_VORBIS_NO_STDIO +int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output) +{ + int data_len, offset, total, limit, error; + short *data; + stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL); + if (v == NULL) return -1; + limit = v->channels * 4096; + *channels = v->channels; + if (sample_rate) + *sample_rate = v->sample_rate; + offset = data_len = 0; + total = limit; + data = (short *) malloc(total * sizeof(*data)); + if (data == NULL) { + stb_vorbis_close(v); + return -2; + } + for (;;) { + int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); + if (n == 0) break; + data_len += n; + offset += n * v->channels; + if (offset + limit > total) { + short *data2; + total *= 2; + data2 = (short *) realloc(data, total * sizeof(*data)); + if (data2 == NULL) { + free(data); + stb_vorbis_close(v); + return -2; + } + data = data2; + } + } + *output = data; + stb_vorbis_close(v); + return data_len; +} +#endif // NO_STDIO + +int stb_vorbis_decode_memory(const uint8 *mem, int len, int *channels, int *sample_rate, short **output) +{ + int data_len, offset, total, limit, error; + short *data; + stb_vorbis *v = stb_vorbis_open_memory(mem, len, &error, NULL); + if (v == NULL) return -1; + limit = v->channels * 4096; + *channels = v->channels; + if (sample_rate) + *sample_rate = v->sample_rate; + offset = data_len = 0; + total = limit; + data = (short *) malloc(total * sizeof(*data)); + if (data == NULL) { + stb_vorbis_close(v); + return -2; + } + for (;;) { + int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); + if (n == 0) break; + data_len += n; + offset += n * v->channels; + if (offset + limit > total) { + short *data2; + total *= 2; + data2 = (short *) realloc(data, total * sizeof(*data)); + if (data2 == NULL) { + free(data); + stb_vorbis_close(v); + return -2; + } + data = data2; + } + } + *output = data; + stb_vorbis_close(v); + return data_len; +} +#endif // STB_VORBIS_NO_INTEGER_CONVERSION + +int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats) +{ + float **outputs; + int len = num_floats / channels; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) { + int i,j; + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + for (j=0; j < k; ++j) { + for (i=0; i < z; ++i) + *buffer++ = f->channel_buffers[i][f->channel_buffer_start+j]; + for ( ; i < channels; ++i) + *buffer++ = 0; + } + n += k; + f->channel_buffer_start += k; + if (n == len) + break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) + break; + } + return n; +} + +int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples) +{ + float **outputs; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < num_samples) { + int i; + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= num_samples) k = num_samples - n; + if (k) { + for (i=0; i < z; ++i) + memcpy(buffer[i]+n, f->channel_buffers[i]+f->channel_buffer_start, sizeof(float)*k); + for ( ; i < channels; ++i) + memset(buffer[i]+n, 0, sizeof(float) * k); + } + n += k; + f->channel_buffer_start += k; + if (n == num_samples) + break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) + break; + } + return n; +} +#endif // STB_VORBIS_NO_PULLDATA_API + +/* Version history + 1.17 - 2019-07-08 - fix CVE-2019-13217, -13218, -13219, -13220, -13221, -13222, -13223 + found with Mayhem by ForAllSecure + 1.16 - 2019-03-04 - fix warnings + 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found + 1.14 - 2018-02-11 - delete bogus dealloca usage + 1.13 - 2018-01-29 - fix truncation of last frame (hopefully) + 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files + 1.11 - 2017-07-23 - fix MinGW compilation + 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory + 1.09 - 2016-04-04 - back out 'avoid discarding last frame' fix from previous version + 1.08 - 2016-04-02 - fixed multiple warnings; fix setup memory leaks; + avoid discarding last frame of audio data + 1.07 - 2015-01-16 - fixed some warnings, fix mingw, const-correct API + some more crash fixes when out of memory or with corrupt files + 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson) + some crash fixes when out of memory or with corrupt files + 1.05 - 2015-04-19 - don't define __forceinline if it's redundant + 1.04 - 2014-08-27 - fix missing const-correct case in API + 1.03 - 2014-08-07 - Warning fixes + 1.02 - 2014-07-09 - Declare qsort compare function _cdecl on windows + 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float + 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in multichannel + (API change) report sample rate for decode-full-file funcs + 0.99996 - bracket #include for macintosh compilation by Laurent Gomila + 0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem + 0.99994 - change fast-float-to-int to work in single-precision FPU mode, remove endian-dependence + 0.99993 - remove assert that fired on legal files with empty tables + 0.99992 - rewind-to-start + 0.99991 - bugfix to stb_vorbis_get_samples_short by Bernhard Wodo + 0.9999 - (should have been 0.99990) fix no-CRT support, compiling as C++ + 0.9998 - add a full-decode function with a memory source + 0.9997 - fix a bug in the read-from-FILE case in 0.9996 addition + 0.9996 - query length of vorbis stream in samples/seconds + 0.9995 - bugfix to another optimization that only happened in certain files + 0.9994 - bugfix to one of the optimizations that caused significant (but inaudible?) errors + 0.9993 - performance improvements; runs in 99% to 104% of time of reference implementation + 0.9992 - performance improvement of IMDCT; now performs close to reference implementation + 0.9991 - performance improvement of IMDCT + 0.999 - (should have been 0.9990) performance improvement of IMDCT + 0.998 - no-CRT support from Casey Muratori + 0.997 - bugfixes for bugs found by Terje Mathisen + 0.996 - bugfix: fast-huffman decode initialized incorrectly for sparse codebooks; fixing gives 10% speedup - found by Terje Mathisen + 0.995 - bugfix: fix to 'effective' overrun detection - found by Terje Mathisen + 0.994 - bugfix: garbage decode on final VQ symbol of a non-multiple - found by Terje Mathisen + 0.993 - bugfix: pushdata API required 1 extra byte for empty page (failed to consume final page if empty) - found by Terje Mathisen + 0.992 - fixes for MinGW warning + 0.991 - turn fast-float-conversion on by default + 0.990 - fix push-mode seek recovery if you seek into the headers + 0.98b - fix to bad release of 0.98 + 0.98 - fix push-mode seek recovery; robustify float-to-int and support non-fast mode + 0.97 - builds under c++ (typecasting, don't use 'class' keyword) + 0.96 - somehow MY 0.95 was right, but the web one was wrong, so here's my 0.95 rereleased as 0.96, fixes a typo in the clamping code + 0.95 - clamping code for 16-bit functions + 0.94 - not publically released + 0.93 - fixed all-zero-floor case (was decoding garbage) + 0.92 - fixed a memory leak + 0.91 - conditional compiles to omit parts of the API and the infrastructure to support them: STB_VORBIS_NO_PULLDATA_API, STB_VORBIS_NO_PUSHDATA_API, STB_VORBIS_NO_STDIO, STB_VORBIS_NO_INTEGER_CONVERSION + 0.90 - first public release +*/ + +#endif // STB_VORBIS_HEADER_ONLY + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/scene.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/scene.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,91 @@ +import std/tables +import std/sequtils +import std/strformat +import std/hashes + +import ./core +import ./mesh +import ./material + +type + Scene* = object + name*: string + shaderGlobals*: Table[string, DataList] + meshes*: seq[Mesh] + dirtyShaderGlobals: seq[string] + loaded*: bool = false + +proc add*(scene: var Scene, mesh: MeshObject) = + assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add meshes" + var tmp = new Mesh + tmp[] = mesh + scene.meshes.add tmp + +proc add*(scene: var Scene, mesh: Mesh) = + assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add meshes" + assert not mesh.isNil, "Cannot add a mesh that is 'nil'" + scene.meshes.add mesh + +proc add*(scene: var Scene, meshes: seq[Mesh]) = + assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add meshes" + for mesh in meshes: + assert not mesh.isNil, "Cannot add a mesh that is 'nil'" + scene.meshes.add meshes + +# generic way to add objects that have a mesh-attribute +proc add*[T](scene: var Scene, obj: T) = + assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add meshes" + for name, value in obj.fieldPairs: + when typeof(value) is Mesh: + assert not value.isNil, "Cannot add a mesh that is 'nil': " & name + scene.meshes.add value + when typeof(value) is seq[Mesh]: + assert not value.isNil, &"Cannot add a mesh that is 'nil': " & name + scene.meshes.add value + +proc addShaderGlobal*[T](scene: var Scene, name: string, data: T) = + assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add shader values" + scene.shaderGlobals[name] = initDataList(thetype=getDataType[T]()) + setValues(scene.shaderGlobals[name], @[data]) + scene.dirtyShaderGlobals.add name + +proc addShaderGlobalArray*[T](scene: var Scene, name: string, data: openArray[T]) = + assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add shader values" + scene.shaderGlobals[name] = initDataList(data) + scene.dirtyShaderGlobals.add name + +func getShaderGlobal*[T](scene: Scene, name: string): T = + getValues[T](scene.shaderGlobals[name])[0] + +func getShaderGlobalArray*[T](scene: Scene, name: string): seq[T] = + getValues[T](scene.shaderGlobals[name]) + +proc setShaderGlobal*[T](scene: var Scene, name: string, value: T) = + setValues[T](scene.shaderGlobals[name], @[value]) + if not scene.dirtyShaderGlobals.contains(name): + scene.dirtyShaderGlobals.add name + +proc setShaderGlobalArray*[T](scene: var Scene, name: string, value: seq[T]) = + setValues[T](scene.shaderGlobals[name], value) + if not scene.dirtyShaderGlobals.contains(name): + scene.dirtyShaderGlobals.add name + +func dirtyShaderGlobals*(scene: Scene): seq[string] = + scene.dirtyShaderGlobals + +func clearDirtyShaderGlobals*(scene: var Scene) = + scene.dirtyShaderGlobals.reset + +func hash*(scene: Scene): Hash = + hash(scene.name) + +func `==`*(a, b: Scene): bool = + a.name == b.name + +func usesMaterial*(scene: Scene, materialType: MaterialType): bool = + return scene.meshes.anyIt(it.material.theType == materialType) + +func getMaterials*(scene: Scene, materialType: MaterialType): seq[MaterialData] = + for mesh in scene.meshes: + if mesh.material.theType == materialType and (not result.contains(mesh.material)): + result.add mesh.material diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/settings.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/settings.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,104 @@ +import std/logging +import std/streams +import std/parsecfg +import std/strutils +import std/parseutils +import std/strformat +import std/tables +import std/os + +import ./core + +when CONFIGHOTRELOAD: + var + configUpdates: Channel[(string, string)] + configUpdates.open() + +# runtime configuration +# ===================== +# namespace is the path from the CONFIGROOT to the according settings file without the file extension +# a settings file must always have the extension CONFIGEXTENSION +# a fully qualified settings identifier can be in the form {namespace}.{section}.{key} +# {key} and {section} may not contain dots + +# a "namespace" is the path from the settings root to an *.CONFIGEXTENSION file, without the file extension +# settings is a namespace <-> settings mapping +var allsettings: Table[string, Config] + +proc configRoot(): string = + joinPath(absolutePath(getAppDir()), CONFIGROOT) + +proc getFile(namespace: string): string = + joinPath(configRoot(), namespace & "." & CONFIGEXTENSION) + +iterator walkConfigNamespaces(): string = + for file in walkDirRec(dir=configRoot(), relative=true, checkDir=true): + if file.endsWith("." & CONFIGEXTENSION): + yield file[0 ..< ^(CONFIGEXTENSION.len + 1)] + +proc loadAllConfig(): Table[string, Config] = + for ns in walkConfigNamespaces(): + result[ns] = ns.getFile().loadConfig() + +proc reloadSettings*() = + allsettings = loadAllConfig() + +proc configStr(key, section, namespace: string): string = + when CONFIGHOTRELOAD: + while configUpdates.peek() > 0: + let (updatedNamespace, updatedConfig) = configUpdates.recv() + allsettings[updatedNamespace] = loadConfig(newStringStream(updatedConfig)) + if not allsettings.hasKey(namespace): + raise newException(Exception, &"Settings {namespace}.{section}.{key} was not found") + allsettings[namespace].getSectionValue(section, key) + +proc setting*[T: int|float|string](key, section, namespace: string): T = + when T is int: + let value = configStr(key, section, namespace) + if parseInt(value, result) == 0: + raise newException(Exception, &"Unable to parse int from settings {namespace}.{section}.{key}: {value}") + elif T is float: + let value = configStr(key, section, namespace) + if parseFloat(value, result) == 0: + raise newException(Exception, &"Unable to parse float from settings {namespace}.{section}.{key}: {value}") + else: + result = configStr(key, section, namespace) + +proc setting*[T: int|float|string](identifier: string): T = + # identifier can be in the form: + # {namespace}.{key} + # {namespace}.{section}.{key} + let parts = identifier.rsplit(".") + if parts.len == 1: + raise newException(Exception, &"Setting with name {identifier} has no namespace") + if parts.len == 2: result = setting[T](parts[1], "", parts[0]) + else: result = setting[T](parts[^1], parts[^2], joinPath(parts[0 .. ^3])) + +proc hadConfigUpdate*(): bool = + when CONFIGHOTRELOAD == true: + result = configUpdates.peek() > 0 + +allsettings = loadAllConfig() + +when CONFIGHOTRELOAD == true: + import std/times + + proc configFileWatchdog() {.thread.} = + var configModTimes: Table[string, Time] + while true: + for namespace in walkConfigNamespaces(): + if not (namespace in configModTimes): + configModTimes[namespace] = Time() + let lastMod = namespace.getFile().getLastModificationTime() + if lastMod > configModTimes[namespace]: + configModTimes[namespace] = lastMod + let configStr = newFileStream(namespace.getFile()).readAll() + configUpdates.send((namespace, configStr)) + sleep CONFIGHOTRELOADINTERVAL + var thethread: Thread[void] + createThread(thethread, configFileWatchdog) + +if DEBUG: + setLogFilter(lvlAll) +else: + setLogFilter(lvlWarn) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/telemetry.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/telemetry.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,1 @@ +# curl -X POST https://semicongine-telemetry.clients1.basx.dev/telemetry/telemetry/event/submit/log/test/1.0/2342343 -v -H "project-api-key: test-key-42" diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/text.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/text.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,126 @@ +import std/tables +import std/unicode +import std/strformat + +import ./core +import ./mesh +import ./material +import ./vulkan/shader + +const SHADER_ATTRIB_PREFIX = "semicon_text_" +var instanceCounter = 0 + +type + TextAlignment = enum + Left + Center + Right + Textbox* = object + maxLen*: int + text: seq[Rune] + dirty: bool + alignment*: TextAlignment = Center + font*: Font + mesh*: Mesh + +const + TRANSFORM_ATTRIB = "transform" + POSITION_ATTRIB = SHADER_ATTRIB_PREFIX & "position" + UV_ATTRIB = SHADER_ATTRIB_PREFIX & "uv" + TEXT_MATERIAL_TYPE* = MaterialType( + name: "default-text-material-type", + vertexAttributes: {TRANSFORM_ATTRIB: Mat4F32, POSITION_ATTRIB: Vec3F32, UV_ATTRIB: Vec2F32}.toTable, + attributes: {"fontAtlas": TextureType}.toTable, + ) + TEXT_SHADER* = createShaderConfiguration( + inputs=[ + attr[Mat4](TRANSFORM_ATTRIB, memoryPerformanceHint=PreferFastWrite, perInstance=true), + attr[Vec3f](POSITION_ATTRIB, memoryPerformanceHint=PreferFastWrite), + attr[Vec2f](UV_ATTRIB, memoryPerformanceHint=PreferFastWrite), + ], + intermediates=[attr[Vec2f]("uvFrag")], + outputs=[attr[Vec4f]("color")], + samplers=[attr[Texture]("fontAtlas")], + vertexCode= &"""gl_Position = vec4({POSITION_ATTRIB}, 1.0) * {TRANSFORM_ATTRIB}; uvFrag = {UV_ATTRIB};""", + fragmentCode= &"""color = texture(fontAtlas, uvFrag);""", + ) + +proc updateMesh(textbox: var Textbox) = + + # pre-calculate text-width + var width = 0'f32 + for i in 0 ..< min(textbox.text.len, textbox.maxLen): + width += textbox.font.glyphs[textbox.text[i]].advance + if i < textbox.text.len - 1: + width += textbox.font.kerning[(textbox.text[i], textbox.text[i + 1])] + + let centerX = width / 2 + let centerY = textbox.font.maxHeight / 2 + + var offsetX = 0'f32 + for i in 0 ..< textbox.maxLen: + let vertexOffset = i * 4 + if i < textbox.text.len: + let + glyph = textbox.font.glyphs[textbox.text[i]] + left = offsetX + glyph.leftOffset + right = offsetX + glyph.leftOffset + glyph.dimension.x + top = glyph.topOffset + bottom = glyph.topOffset + glyph.dimension.y + + textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f(left - centerX, bottom + centerY) + textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f(left - centerX, top + centerY) + textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f(right - centerX, top + centerY) + textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f(right - centerX, bottom + centerY) + + textbox.mesh[UV_ATTRIB, vertexOffset + 0] = glyph.uvs[0] + textbox.mesh[UV_ATTRIB, vertexOffset + 1] = glyph.uvs[1] + textbox.mesh[UV_ATTRIB, vertexOffset + 2] = glyph.uvs[2] + textbox.mesh[UV_ATTRIB, vertexOffset + 3] = glyph.uvs[3] + + offsetX += glyph.advance + if i < textbox.text.len - 1: + offsetX += textbox.font.kerning[(textbox.text[i], textbox.text[i + 1])] + else: + textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f() + textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f() + textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f() + textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f() + + +func text*(textbox: Textbox): seq[Rune] = + textbox.text + +proc `text=`*(textbox: var Textbox, text: seq[Rune]) = + textbox.text = text + textbox.updateMesh() +proc `text=`*(textbox: var Textbox, text: string) = + `text=`(textbox, text.toRunes) + +proc initTextbox*(maxLen: int, font: Font, text="".toRunes): Textbox = + var + positions = newSeq[Vec3f](int(maxLen * 4)) + indices: seq[array[3, uint16]] + uvs = newSeq[Vec2f](int(maxLen * 4)) + for i in 0 ..< maxLen: + let offset = i * 4 + indices.add [ + [uint16(offset + 0), uint16(offset + 1), uint16(offset + 2)], + [uint16(offset + 2), uint16(offset + 3), uint16(offset + 0)], + ] + + result = Textbox(maxLen: maxLen, text: text, font: font, dirty: true) + result.mesh = newMesh(positions = positions, indices = indices, uvs = uvs, name = &"textbox-{instanceCounter}") + inc instanceCounter + result.mesh[].renameAttribute("position", POSITION_ATTRIB) + result.mesh[].renameAttribute("uv", UV_ATTRIB) + result.mesh.material = MaterialData( + theType: TEXT_MATERIAL_TYPE, + name: font.name & " text", + attributes: {"fontAtlas": initDataList(@[font.fontAtlas])}.toTable, + ) + + result.updateMesh() + +proc initTextbox*(maxLen: int, font: Font, text=""): Textbox = + initTextbox(maxLen=maxLen, font=font, text=text.toRunes) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,28 @@ +import ./vulkan/instance +import ./vulkan/physicaldevice +import ./vulkan/device +import ./vulkan/swapchain +import ./vulkan/renderpass +import ./vulkan/framebuffer +import ./vulkan/commandbuffer +import ./vulkan/syncing +import ./vulkan/shader +import ./vulkan/descriptor +import ./vulkan/pipeline +import ./vulkan/buffer +import ./vulkan/memory + +export instance +export physicaldevice +export device +export swapchain +export renderpass +export framebuffer +export commandbuffer +export syncing +export shader +export descriptor +export pipeline +export buffer +export memory + diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/buffer.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/buffer.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,146 @@ +import std/strformat +import std/typetraits +import std/sequtils +import std/tables +import std/logging + +import ../core +import ./device +import ./memory +import ./physicaldevice +import ./commandbuffer + +type + Buffer* = object + device*: Device + vk*: VkBuffer + size*: int + usage*: seq[VkBufferUsageFlagBits] + case memoryAllocated*: bool + of false: discard + of true: + memory*: DeviceMemory + + +proc `==`*(a, b: Buffer): bool = + a.vk == b.vk + +func `$`*(buffer: Buffer): string = + &"Buffer(vk: {buffer.vk}, size: {buffer.size}, usage: {buffer.usage})" + +proc requirements(buffer: Buffer): MemoryRequirements = + assert buffer.vk.valid + assert buffer.device.vk.valid + var req: VkMemoryRequirements + buffer.device.vk.vkGetBufferMemoryRequirements(buffer.vk, addr req) + result.size = req.size + result.alignment = req.alignment + let memorytypes = buffer.device.physicaldevice.vk.getMemoryProperties().types + for i in 0 ..< sizeof(req.memoryTypeBits) * 8: + if ((req.memoryTypeBits shr i) and 1) == 1: + result.memoryTypes.add memorytypes[i] + +proc allocateMemory(buffer: var Buffer, requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool) = + assert buffer.device.vk.valid + assert buffer.memoryAllocated == false + + let requirements = buffer.requirements() + let memoryType = requirements.memoryTypes.selectBestMemoryType( + requireMappable=requireMappable, + preferVRAM=preferVRAM, + preferAutoFlush=preferAutoFlush + ) + + debug "Allocating memory for buffer: ", buffer.size, " bytes of type ", memoryType + # need to replace the whole buffer object, due to case statement + buffer = Buffer( + device: buffer.device, + vk: buffer.vk, + size: buffer.size, + usage: buffer.usage, + memoryAllocated: true, + memory: buffer.device.allocate(requirements.size, memoryType) + ) + checkVkResult buffer.device.vk.vkBindBufferMemory(buffer.vk, buffer.memory.vk, VkDeviceSize(0)) + +# currently no support for extended structure and concurrent/shared use +# (shardingMode = VK_SHARING_MODE_CONCURRENT not supported) +proc createBuffer*( + device: Device, + size: int, + usage: openArray[VkBufferUsageFlagBits], + requireMappable: bool, + preferVRAM: bool, + preferAutoFlush=true, +): Buffer = + assert device.vk.valid + assert size > 0 + + result.device = device + result.size = size + result.usage = usage.toSeq + if not requireMappable: + result.usage.add VK_BUFFER_USAGE_TRANSFER_DST_BIT + var createInfo = VkBufferCreateInfo( + sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + flags: VkBufferCreateFlags(0), + size: uint64(size), + usage: toBits(result.usage), + sharingMode: VK_SHARING_MODE_EXCLUSIVE, + ) + + checkVkResult vkCreateBuffer( + device=device.vk, + pCreateInfo=addr createInfo, + pAllocator=nil, + pBuffer=addr result.vk + ) + result.allocateMemory(requireMappable=requireMappable, preferVRAM=preferVRAM, preferAutoFlush=preferAutoFlush) + + +proc copy*(src, dst: Buffer, dstOffset=0) = + assert src.device.vk.valid + assert dst.device.vk.valid + assert src.device == dst.device + assert src.size <= dst.size - dstOffset + assert VK_BUFFER_USAGE_TRANSFER_SRC_BIT in src.usage + assert VK_BUFFER_USAGE_TRANSFER_DST_BIT in dst.usage + + var copyRegion = VkBufferCopy(size: VkDeviceSize(src.size), dstOffset: VkDeviceSize(dstOffset)) + withSingleUseCommandBuffer(src.device, true, commandBuffer): + commandBuffer.vkCmdCopyBuffer(src.vk, dst.vk, 1, addr(copyRegion)) + +proc destroy*(buffer: var Buffer) = + assert buffer.device.vk.valid + assert buffer.vk.valid + buffer.device.vk.vkDestroyBuffer(buffer.vk, nil) + if buffer.memoryAllocated: + assert buffer.memory.vk.valid + buffer.memory.free + buffer = Buffer( + device: buffer.device, + vk: buffer.vk, + size: buffer.size, + usage: buffer.usage, + memoryAllocated: false, + ) + buffer.vk.reset + +proc setData*(dst: Buffer, src: pointer, size: int, bufferOffset=0) = + assert bufferOffset + size <= dst.size + if dst.memory.canMap: + copyMem(cast[pointer](cast[int](dst.memory.data) + bufferOffset), src, size) + if dst.memory.needsFlushing: + dst.memory.flush() + else: # use staging buffer, slower but required if memory is not host visible + var stagingBuffer = dst.device.createBuffer(size, [VK_BUFFER_USAGE_TRANSFER_SRC_BIT], requireMappable=true, preferVRAM=false, preferAutoFlush=true) + setData(stagingBuffer, src, size, 0) + stagingBuffer.copy(dst, bufferOffset) + stagingBuffer.destroy() + +proc setData*[T: seq](dst: Buffer, src: ptr T, offset=0'u64) = + dst.setData(src, sizeof(get(genericParams(T), 0)) * src[].len, offset=offset) + +proc setData*[T](dst: Buffer, src: ptr T, offset=0'u64) = + dst.setData(src, sizeof(T), offset=offset) + diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/commandbuffer.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/commandbuffer.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,70 @@ +import ../core +import ./device +import ./physicaldevice + +type + CommandBufferPool* = object + device: Device + vk*: VkCommandPool + family*: QueueFamily + buffers*: seq[VkCommandBuffer] + +proc createCommandBufferPool*(device: Device, family: QueueFamily, nBuffers: int): CommandBufferPool = + assert device.vk.valid + var createInfo = VkCommandPoolCreateInfo( + sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT], + queueFamilyIndex: family.index, + ) + result.family = family + result.device = device + checkVkResult device.vk.vkCreateCommandPool(addr(createInfo), nil, addr(result.vk)) + + var allocInfo = VkCommandBufferAllocateInfo( + sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + commandPool: result.vk, + level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, + commandBufferCount: uint32(nBuffers), + ) + result.buffers = newSeq[VkCommandBuffer](nBuffers) + checkVkResult device.vk.vkAllocateCommandBuffers(addr(allocInfo), result.buffers.toCPointer) + + +template withSingleUseCommandBuffer*(device: Device, needsTransfer: bool, commandBuffer, body: untyped): untyped = + assert device.vk.valid + + var queue: Queue + for q in device.queues.values: + if q.family.canDoTransfer or not needsTransfer: + queue = q + break + if not queue.vk.valid: + raise newException(Exception, "No queue that supports buffer transfer") + + var + commandBufferPool = createCommandBufferPool(device, queue.family, 1) + commandBuffer = commandBufferPool.buffers[0] + beginInfo = VkCommandBufferBeginInfo( + sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT), + ) + checkVkResult commandBuffer.vkBeginCommandBuffer(addr(beginInfo)) + + block: + body + + checkVkResult commandBuffer.vkEndCommandBuffer() + var submitInfo = VkSubmitInfo( + sType: VK_STRUCTURE_TYPE_SUBMIT_INFO, + commandBufferCount: 1, + pCommandBuffers: addr(commandBuffer), + ) + checkVkResult queue.vk.vkQueueSubmit(1, addr(submitInfo), VkFence(0)) + checkVkResult queue.vk.vkQueueWaitIdle() + commandBufferPool.destroy() + +proc destroy*(commandpool: var CommandBufferPool) = + assert commandpool.device.vk.valid + assert commandpool.vk.valid + commandpool.device.vk.vkDestroyCommandPool(commandpool.vk, nil) + commandpool.vk.reset diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/descriptor.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/descriptor.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,175 @@ +import std/enumerate +import std/tables + +import ../core +import ./device +import ./buffer +import ./image + +type + DescriptorType* = enum + Uniform, ImageSampler + Descriptor* = object # "fields" of a DescriptorSetLayout + name*: string + count*: int + stages*: seq[VkShaderStageFlagBits] + case thetype*: DescriptorType + of Uniform: + buffer*: Buffer + offset*: int + size*: int + of ImageSampler: + imageviews*: seq[ImageView] + samplers*: seq[VulkanSampler] + DescriptorSet* = object # "instance" of a DescriptorSetLayout + vk*: VkDescriptorSet + layout*: DescriptorSetLayout + DescriptorSetLayout* = object # "type-description" of a DescriptorSet + device: Device + vk*: VkDescriptorSetLayout + descriptors*: seq[Descriptor] + DescriptorPool* = object # required for allocation of DescriptorSet + device: Device + vk*: VkDescriptorPool + maxSets*: int # maximum number of allocatable descriptor sets + counts*: seq[(VkDescriptorType, int)] # maximum number for each descriptor type to allocate + +const DESCRIPTOR_TYPE_MAP = { + Uniform: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + ImageSampler: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, +}.toTable + +func vkType(descriptor: Descriptor): VkDescriptorType = + DESCRIPTOR_TYPE_MAP[descriptor.thetype] + +proc createDescriptorSetLayout*(device: Device, descriptors: seq[Descriptor]): DescriptorSetLayout = + assert device.vk.valid + + result.device = device + result.descriptors = descriptors + + var layoutbindings: seq[VkDescriptorSetLayoutBinding] + for i, descriptor in enumerate(descriptors): + layoutbindings.add VkDescriptorSetLayoutBinding( + binding: uint32(i), + descriptorType: descriptor.vkType, + descriptorCount: uint32(descriptor.count), + stageFlags: toBits descriptor.stages, + pImmutableSamplers: nil, + ) + var layoutCreateInfo = VkDescriptorSetLayoutCreateInfo( + sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + bindingCount: uint32(layoutbindings.len), + pBindings: layoutbindings.toCPointer + ) + checkVkResult vkCreateDescriptorSetLayout(device.vk, addr(layoutCreateInfo), nil, addr(result.vk)) + +proc destroy*(descriptorSetLayout: var DescriptorSetLayout) = + assert descriptorSetLayout.device.vk.valid + assert descriptorSetLayout.vk.valid + descriptorSetLayout.device.vk.vkDestroyDescriptorSetLayout(descriptorSetLayout.vk, nil) + descriptorSetLayout.vk.reset + + +proc createDescriptorSetPool*(device: Device, counts: seq[(VkDescriptorType, int)], maxSets = 1000): DescriptorPool = + assert device.vk.valid + + result.device = device + result.maxSets = maxSets + result.counts = counts + + var poolSizes: seq[VkDescriptorPoolSize] + for (thetype, count) in result.counts: + poolSizes.add VkDescriptorPoolSize(thetype: thetype, descriptorCount: uint32(count)) + var poolInfo = VkDescriptorPoolCreateInfo( + sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + poolSizeCount: uint32(poolSizes.len), + pPoolSizes: poolSizes.toCPointer, + maxSets: uint32(result.maxSets), + ) + checkVkResult vkCreateDescriptorPool(result.device.vk, addr(poolInfo), nil, addr(result.vk)) + +proc reset*(pool: DescriptorPool) = + assert pool.device.vk.valid + assert pool.vk.valid + checkVkResult vkResetDescriptorPool(pool.device.vk, pool.vk, VkDescriptorPoolResetFlags(0)) + +proc destroy*(pool: var DescriptorPool) = + assert pool.device.vk.valid + assert pool.vk.valid + pool.device.vk.vkDestroyDescriptorPool(pool.vk, nil) + pool.vk.reset + +proc allocateDescriptorSet*(pool: DescriptorPool, layout: DescriptorSetLayout, nframes: int): seq[DescriptorSet] = + assert pool.device.vk.valid + assert pool.vk.valid + assert layout.device.vk.valid + assert layout.vk.valid + + var layouts: seq[VkDescriptorSetLayout] + var descriptorSets = newSeq[VkDescriptorSet](nframes) + for i in 0 ..< nframes: + layouts.add layout.vk + var allocInfo = VkDescriptorSetAllocateInfo( + sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + descriptorPool: pool.vk, + descriptorSetCount: uint32(layouts.len), + pSetLayouts: layouts.toCPointer, + ) + + checkVkResult vkAllocateDescriptorSets(pool.device.vk, addr(allocInfo), descriptorSets.toCPointer) + for descriptorSet in descriptorSets: + result.add DescriptorSet(vk: descriptorSet, layout: layout) + +proc writeDescriptorSet*(descriptorSet: DescriptorSet, bindingBase=0'u32) = + # assumes descriptors of the descriptorSet are arranged interleaved in buffer + assert descriptorSet.layout.device.vk.valid + assert descriptorSet.layout.vk.valid + assert descriptorSet.vk.valid + + var descriptorSetWrites: seq[VkWriteDescriptorSet] + var bufferInfos: seq[VkDescriptorBufferInfo] + + var i = bindingBase + # need to keep this sequence out of the loop, otherwise it will be + # gc-ed before the final update call and pointers are invalid :( + var imgInfos: seq[seq[VkDescriptorImageInfo]] + for descriptor in descriptorSet.layout.descriptors: + if descriptor.thetype == Uniform: + assert descriptor.buffer.vk.valid + bufferInfos.add VkDescriptorBufferInfo( + buffer: descriptor.buffer.vk, + offset: uint64(descriptor.offset), + range: uint64(descriptor.size), + ) + descriptorSetWrites.add VkWriteDescriptorSet( + sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + dstSet: descriptorSet.vk, + dstBinding: i, + dstArrayElement: 0, + descriptorType: descriptor.vkType, + descriptorCount: uint32(descriptor.count), + pBufferInfo: addr bufferInfos[^1], + ) + elif descriptor.thetype == ImageSampler: + var imgInfo: seq[VkDescriptorImageInfo] + for img_i in 0 ..< descriptor.count: + assert descriptor.imageviews[img_i].vk.valid + assert descriptor.samplers[img_i].vk.valid + imgInfo.add VkDescriptorImageInfo( + imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + imageView: descriptor.imageviews[img_i].vk, + sampler: descriptor.samplers[img_i].vk, + ) + imgInfos.add imgInfo + descriptorSetWrites.add VkWriteDescriptorSet( + sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + dstSet: descriptorSet.vk, + dstBinding: i, + dstArrayElement: 0, + descriptorType: descriptor.vkType, + descriptorCount: uint32(descriptor.count), + pImageInfo: imgInfos[^1].toCPointer, + ) + inc i + descriptorSet.layout.device.vk.vkUpdateDescriptorSets(uint32(descriptorSetWrites.len), descriptorSetWrites.toCPointer, 0, nil) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/device.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/device.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,102 @@ +import std/sequtils +import std/options +import std/tables + +import ../core +import ./instance +import ./physicaldevice + +type + Device* = object + physicalDevice*: PhysicalDevice + vk*: VkDevice + queues*: Table[QueueFamily, Queue] + enabledFeatures*: VkPhysicalDeviceFeatures + Queue* = object + vk*: VkQueue + family*: QueueFamily + presentation: bool + graphics: bool + +proc `$`*(device: Device): string = + "Device: vk=" & $device.vk + +proc createDevice*( + instance: Instance, + physicalDevice: PhysicalDevice, + enabledLayers: seq[string], + enabledExtensions: seq[string], + queueFamilies: seq[QueueFamily], +): Device = + assert instance.vk.valid + assert physicalDevice.vk.valid + assert queueFamilies.len > 0 + + result.physicalDevice = physicalDevice + var allExtensions = enabledExtensions & @["VK_KHR_swapchain"] + for extension in allExtensions: + instance.vk.loadExtension(extension) + var + enabledLayersC = allocCStringArray(enabledLayers) + enabledExtensionsC = allocCStringArray(allExtensions) + priority = 1'f32 + var deviceQueues: Table[QueueFamily, VkDeviceQueueCreateInfo] + for family in queueFamilies: + deviceQueues[family] = VkDeviceQueueCreateInfo( + sType: VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, + queueFamilyIndex: family.index, + queueCount: 1, + pQueuePriorities: addr(priority), + ) + var queueList = deviceQueues.values.toSeq + + var uniformBufferLayoutFeature = VkPhysicalDeviceUniformBufferStandardLayoutFeatures( + stype:VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES, + uniformBufferStandardLayout: true, + ) + var features2 = VkPhysicalDeviceFeatures2( + stype: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + pnext: addr uniformBufferLayoutFeature, + features: result.enabledFeatures, + ) + var createInfo = VkDeviceCreateInfo( + sType: VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, + queueCreateInfoCount: uint32(queueList.len), + pQueueCreateInfos: queueList.toCPointer, + enabledLayerCount: uint32(enabledLayers.len), + ppEnabledLayerNames: enabledLayersC, + enabledExtensionCount: uint32(allExtensions.len), + ppEnabledExtensionNames: enabledExtensionsC, + pEnabledFeatures: nil, + pnext: addr features2, + ) + + checkVkResult vkCreateDevice( + physicalDevice=physicalDevice.vk, + pCreateInfo=addr createInfo, + pAllocator=nil, + pDevice=addr result.vk + ) + deallocCStringArray(enabledLayersC) + deallocCStringArray(enabledExtensionsC) + for family in deviceQueues.keys: + var queue: VkQueue + vkGetDeviceQueue(result.vk, family.index, 0, addr queue) + result.queues[family] = Queue(vk: queue, family: family, presentation: family.canDoPresentation(physicalDevice.surface), graphics: family.canDoGraphics()) + +func firstGraphicsQueue*(device: Device): Option[Queue] = + assert device.vk.valid + for family, queue in device.queues: + if queue.graphics: + return some(queue) + +proc firstPresentationQueue*(device: Device): Option[Queue] = + assert device.vk.valid + for family, queue in device.queues: + if queue.presentation: + return some(queue) + +proc destroy*(device: var Device) = + assert device.vk.valid + device.vk.vkDestroyDevice(nil) + device.vk.reset() diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/drawable.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/drawable.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,59 @@ +import std/tables +import std/strformat +import std/logging + +import ../core +import ./buffer + +type + Drawable* = object + name*: string + elementCount*: int # number of vertices or indices + bufferOffsets*: Table[VkPipeline, seq[(string, MemoryPerformanceHint, int)]] # list of buffers and list of offset for each attribute in that buffer + instanceCount*: int # number of instance + case indexed*: bool + of true: + indexType*: VkIndexType + indexBufferOffset*: int + of false: + discard + +func `$`*(drawable: Drawable): string = + if drawable.indexed: + &"Drawable({drawable.name}, elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, bufferOffsets: {drawable.bufferOffsets}, indexType: {drawable.indexType}, indexBufferOffset: {drawable.indexBufferOffset})" + else: + &"Drawable({drawable.name}, elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, bufferOffsets: {drawable.bufferOffsets})" + +proc draw*(drawable: Drawable, commandBuffer: VkCommandBuffer, vertexBuffers: Table[MemoryPerformanceHint, Buffer], indexBuffer: Buffer, pipeline: VkPipeline) = + debug "Draw ", drawable + + var buffers: seq[VkBuffer] + var offsets: seq[VkDeviceSize] + + + for (name, performanceHint, offset) in drawable.bufferOffsets[pipeline]: + buffers.add vertexBuffers[performanceHint].vk + offsets.add VkDeviceSize(offset) + + commandBuffer.vkCmdBindVertexBuffers( + firstBinding=0'u32, + bindingCount=uint32(buffers.len), + pBuffers=buffers.toCPointer(), + pOffsets=offsets.toCPointer() + ) + if drawable.indexed: + commandBuffer.vkCmdBindIndexBuffer(indexBuffer.vk, VkDeviceSize(drawable.indexBufferOffset), drawable.indexType) + commandBuffer.vkCmdDrawIndexed( + indexCount=uint32(drawable.elementCount), + instanceCount=uint32(drawable.instanceCount), + firstIndex=0, + vertexOffset=0, + firstInstance=0 + ) + else: + commandBuffer.vkCmdDraw( + vertexCount=uint32(drawable.elementCount), + instanceCount=uint32(drawable.instanceCount), + firstVertex=0, + firstInstance=0 + ) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/framebuffer.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/framebuffer.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,38 @@ +import ../core +import ./device +import ./image + + +type + Framebuffer* = object + device*: Device + vk*: VkFramebuffer + dimension*: Vec2u + +proc createFramebuffer*(device: Device, renderpass: VkRenderPass, attachments: openArray[ImageView], dimension: Vec2u): Framebuffer = + assert device.vk.valid + assert renderpass.valid + + result.device = device + result.dimension = dimension + + var theattachments: seq[VkImageView] + for a in attachments: + assert a.vk.valid + theattachments.add a.vk + var framebufferInfo = VkFramebufferCreateInfo( + sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + renderPass: renderpass, + attachmentCount: uint32(theattachments.len), + pAttachments: theattachments.toCPointer, + width: dimension[0], + height: dimension[1], + layers: 1, + ) + checkVkResult device.vk.vkCreateFramebuffer(addr(framebufferInfo), nil, addr(result.vk)) + +proc destroy*(framebuffer: var Framebuffer) = + assert framebuffer.device.vk.valid + assert framebuffer.vk.valid + framebuffer.device.vk.vkDestroyFramebuffer(framebuffer.vk, nil) + framebuffer.vk.reset diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/image.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/image.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,291 @@ +import std/strformat +import std/tables +import std/logging + +import ../core +import ./device +import ./physicaldevice +import ./buffer +import ./memory +import ./commandbuffer + +type + PixelDepth = 1 .. 4 + VulkanImage* = object + device*: Device + vk*: VkImage + width*: int # pixel + height*: int # pixel + depth*: PixelDepth + format*: VkFormat + usage*: seq[VkImageUsageFlagBits] + case memoryAllocated*: bool + of false: discard + of true: + memory*: DeviceMemory + VulkanSampler* = object + device*: Device + vk*: VkSampler + ImageView* = object + vk*: VkImageView + image*: VulkanImage + VulkanTexture* = object + image*: VulkanImage + imageView*: ImageView + sampler*: VulkanSampler + +const DEPTH_FORMAT_MAP = { + PixelDepth(1): VK_FORMAT_R8_SRGB, + PixelDepth(2): VK_FORMAT_R8G8_SRGB, + PixelDepth(3): VK_FORMAT_R8G8B8_SRGB, + PixelDepth(4): VK_FORMAT_R8G8B8A8_SRGB, +}.toTable + + +proc requirements(image: VulkanImage): MemoryRequirements = + assert image.vk.valid + assert image.device.vk.valid + var req: VkMemoryRequirements + image.device.vk.vkGetImageMemoryRequirements(image.vk, addr req) + result.size = req.size + result.alignment = req.alignment + let memorytypes = image.device.physicaldevice.vk.getMemoryProperties().types + for i in 0 ..< sizeof(req.memoryTypeBits) * 8: + if ((req.memoryTypeBits shr i) and 1) == 1: + result.memoryTypes.add memorytypes[i] + +proc allocateMemory(image: var VulkanImage, requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool) = + assert image.device.vk.valid + assert image.memoryAllocated == false + + let requirements = image.requirements() + let memoryType = requirements.memoryTypes.selectBestMemoryType( + requireMappable=requireMappable, + preferVRAM=preferVRAM, + preferAutoFlush=preferAutoFlush + ) + + debug "Allocating memory for image: ", image.width, "x", image.height, "x", image.depth, ", ", requirements.size, " bytes of type ", memoryType + image = VulkanImage( + device: image.device, + vk: image.vk, + width: image.width, + height: image.height, + depth: image.depth, + format: image.format, + usage: image.usage, + memoryAllocated: true, + memory: image.device.allocate(requirements.size, memoryType), + ) + checkVkResult image.device.vk.vkBindImageMemory(image.vk, image.memory.vk, VkDeviceSize(0)) + +proc transitionImageLayout*(image: VulkanImage, oldLayout, newLayout: VkImageLayout) = + var barrier = VkImageMemoryBarrier( + sType: VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + oldLayout: oldLayout, + newLayout: newLayout, + srcQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED, + dstQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED, + image: image.vk, + subresourceRange: VkImageSubresourceRange( + aspectMask: toBits [VK_IMAGE_ASPECT_COLOR_BIT], + baseMipLevel: 0, + levelCount: 1, + baseArrayLayer: 0, + layerCount: 1, + ), + ) + var + sourceStage, destinationStage: VkPipelineStageFlagBits + if oldLayout == VK_IMAGE_LAYOUT_UNDEFINED and newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + barrier.srcAccessMask = VkAccessFlags(0) + barrier.dstAccessMask = toBits [VK_ACCESS_TRANSFER_WRITE_BIT] + sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT + destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT + elif oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL and newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + barrier.srcAccessMask = toBits [VK_ACCESS_TRANSFER_WRITE_BIT] + barrier.dstAccessMask = toBits [VK_ACCESS_SHADER_READ_BIT] + sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT + destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT + else: + raise newException(Exception, "Unsupported layout transition!") + + withSingleUseCommandBuffer(image.device, false, commandBuffer): + vkCmdPipelineBarrier( + commandBuffer, + toBits [sourceStage], toBits [destinationStage], + VkDependencyFlags(0), + 0, nil, + 0, nil, + 1, addr barrier + ) + +proc copy*(src: Buffer, dst: VulkanImage) = + assert src.device.vk.valid + assert dst.device.vk.valid + assert src.device == dst.device + assert VK_BUFFER_USAGE_TRANSFER_SRC_BIT in src.usage + assert VK_IMAGE_USAGE_TRANSFER_DST_BIT in dst.usage + + var region = VkBufferImageCopy( + bufferOffset: 0, + bufferRowLength: 0, + bufferImageHeight: 0, + imageSubresource: VkImageSubresourceLayers( + aspectMask: toBits [VK_IMAGE_ASPECT_COLOR_BIT], + mipLevel: 0, + baseArrayLayer: 0, + layerCount: 1, + ), + imageOffset: VkOffset3D(x: 0, y: 0, z: 0), + imageExtent: VkExtent3D(width: uint32(dst.width), height: uint32(dst.height), depth: 1) + ) + withSingleUseCommandBuffer(src.device, true, commandBuffer): + commandBuffer.vkCmdCopyBufferToImage( + src.vk, + dst.vk, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + addr region + ) + +# currently only usable for texture access from shader +proc createImage*(device: Device, width, height: int, depth: PixelDepth, data: pointer): VulkanImage = + assert device.vk.valid + assert width > 0 + assert height > 0 + assert depth != 2 + assert data != nil + + let size = width * height * depth + result.device = device + result.width = width + result.height = height + result.depth = depth + result.format = DEPTH_FORMAT_MAP[depth] + result.usage = @[VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT] + + var imageInfo = VkImageCreateInfo( + sType: VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + imageType: VK_IMAGE_TYPE_2D, + extent: VkExtent3D(width: uint32(width), height: uint32(height), depth: 1), + mipLevels: 1, + arrayLayers: 1, + format: result.format, + tiling: VK_IMAGE_TILING_OPTIMAL, + initialLayout: VK_IMAGE_LAYOUT_UNDEFINED, + usage: toBits result.usage, + sharingMode: VK_SHARING_MODE_EXCLUSIVE, + samples: VK_SAMPLE_COUNT_1_BIT, + ) + checkVkResult device.vk.vkCreateImage(addr imageInfo, nil, addr result.vk) + result.allocateMemory(requireMappable=false, preferVRAM=true, preferAutoFlush=false) + result.transitionImageLayout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) + + var stagingBuffer = device.createBuffer(size=size, usage=[VK_BUFFER_USAGE_TRANSFER_SRC_BIT], requireMappable=true, preferVRAM=false, preferAutoFlush=true) + stagingBuffer.setData(src=data, size=size) + stagingBuffer.copy(result) + result.transitionImageLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + stagingBuffer.destroy() + +proc destroy*(image: var VulkanImage) = + assert image.device.vk.valid + assert image.vk.valid + image.device.vk.vkDestroyImage(image.vk, nil) + if image.memoryAllocated: + assert image.memory.vk.valid + image.memory.free + image = VulkanImage( + device: image.device, + vk: image.vk, + width: image.width, + height: image.height, + depth: image.depth, + format: image.format, + usage: image.usage, + memoryAllocated: false, + ) + image.vk.reset + +proc createSampler*(device: Device, sampler: Sampler): VulkanSampler = + assert device.vk.valid + var samplerInfo = VkSamplerCreateInfo( + sType: VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + magFilter: sampler.magnification, + minFilter: sampler.minification, + addressModeU: sampler.wrapModeS, + addressModeV: sampler.wrapModeT, + addressModeW: VK_SAMPLER_ADDRESS_MODE_REPEAT, + anisotropyEnable: device.enabledFeatures.samplerAnisotropy, + maxAnisotropy: device.physicalDevice.properties.limits.maxSamplerAnisotropy, + borderColor: VK_BORDER_COLOR_INT_OPAQUE_BLACK, + unnormalizedCoordinates: VK_FALSE, + compareEnable: VK_FALSE, + compareOp: VK_COMPARE_OP_ALWAYS, + mipmapMode: VK_SAMPLER_MIPMAP_MODE_LINEAR, + mipLodBias: 0, + minLod: 0, + maxLod: 0, + ) + result.device = device + checkVkResult device.vk.vkCreateSampler(addr samplerInfo, nil, addr result.vk) + +proc destroy*(sampler: var VulkanSampler) = + assert sampler.device.vk.valid + assert sampler.vk.valid + sampler.device.vk.vkDestroySampler(sampler.vk, nil) + sampler.vk.reset + +proc createImageView*( + image: VulkanImage, + imageviewtype=VK_IMAGE_VIEW_TYPE_2D, + baseMipLevel=0'u32, + levelCount=1'u32, + baseArrayLayer=0'u32, + layerCount=1'u32 +): ImageView = + assert image.device.vk.valid + assert image.vk.valid + + var createInfo = VkImageViewCreateInfo( + sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + image: image.vk, + viewType: imageviewtype, + format: image.format, + components: VkComponentMapping( + r: VK_COMPONENT_SWIZZLE_IDENTITY, + g: VK_COMPONENT_SWIZZLE_IDENTITY, + b: VK_COMPONENT_SWIZZLE_IDENTITY, + a: VK_COMPONENT_SWIZZLE_IDENTITY, + ), + subresourceRange: VkImageSubresourceRange( + aspectMask: VkImageAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT), + baseMipLevel: baseMipLevel, + levelCount: levelCount, + baseArrayLayer: baseArrayLayer, + layerCount: layerCount, + ), + ) + result.image = image + checkVkResult image.device.vk.vkCreateImageView(addr(createInfo), nil, addr(result.vk)) + +proc destroy*(imageview: var ImageView) = + assert imageview.image.device.vk.valid + assert imageview.vk.valid + imageview.image.device.vk.vkDestroyImageView(imageview.vk, nil) + imageview.vk.reset() + +func `$`*(texture: VulkanTexture): string = + &"VulkanTexture({texture.image.width}x{texture.image.height})" + + +proc uploadTexture*(device: Device, texture: Texture): VulkanTexture = + assert device.vk.valid + result.image = createImage(device=device, width=texture.image.width, height=texture.image.height, depth=4, data=addr texture.image.imagedata[0][0]) + result.imageView = result.image.createImageView() + result.sampler = result.image.device.createSampler(texture.sampler) + +proc destroy*(texture: var VulkanTexture) = + texture.image.destroy() + texture.imageView.destroy() + texture.sampler.destroy() diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/instance.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/instance.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,143 @@ +import std/strformat +import std/tables +import std/sequtils +import std/logging + +import ../core + +import ../platform/vulkanExtensions +import ../platform/window +import ../platform/surface + +type + Instance* = object + vk*: VkInstance + window*: NativeWindow + surface*: VkSurfaceKHR + Debugger* = object + instance*: Instance + messenger*: VkDebugUtilsMessengerEXT + DebugCallback* = proc ( + messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, + messageTypes: VkDebugUtilsMessageTypeFlagsEXT, + pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT, + userData: pointer + ): VkBool32 {.cdecl.} + +proc getInstanceExtensions*(): seq[string] = + var extensionCount: uint32 + checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), nil) + if extensionCount > 0: + var extensions = newSeq[VkExtensionProperties](extensionCount) + checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), extensions.toCPointer) + for extension in extensions: + result.add(cleanString(extension.extensionName)) + +proc getLayers*(): seq[string] = + var n_layers: uint32 + checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), nil) + if n_layers > 0: + var layers = newSeq[VkLayerProperties](n_layers) + checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), layers.toCPointer) + for layer in layers: + result.add(cleanString(layer.layerName)) + +proc createInstance*( + window: NativeWindow, + vulkanVersion: uint32, + instanceExtensions: seq[string], + layers: seq[string], + name = "defaultVulkanInstance", + engine = "defaultEngine", +): Instance = + + let requiredExtensions = REQUIRED_PLATFORM_EXTENSIONS & @["VK_KHR_surface"] & instanceExtensions + for i in requiredExtensions: + assert i in getInstanceExtensions(), $i + var availableLayers: seq[string] + for i in layers: + if i in getLayers(): + availableLayers.add i + debug "Enabled layers: " & $availableLayers + var + layersC = allocCStringArray(availableLayers) + instanceExtensionsC = allocCStringArray(requiredExtensions) + appinfo = VkApplicationInfo( + sType: VK_STRUCTURE_TYPE_APPLICATION_INFO, + pApplicationName: name, + pEngineName: engine, + apiVersion: vulkanVersion, + ) + createinfo = VkInstanceCreateInfo( + sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + pApplicationInfo: addr(appinfo), + enabledLayerCount: availableLayers.len.uint32, + ppEnabledLayerNames: layersC, + enabledExtensionCount: requiredExtensions.len.uint32, + ppEnabledExtensionNames: instanceExtensionsC + ) + checkVkResult vkCreateInstance(addr(createinfo), nil, addr(result.vk)) + result.vk.loadVulkan() + deallocCStringArray(layersC) + deallocCStringArray(instanceExtensionsC) + for extension in requiredExtensions: + result.vk.loadExtension($extension) + result.surface = result.vk.createNativeSurface(window) + +proc destroy*(instance: var Instance) = + assert instance.vk.valid + assert instance.surface.valid + # needs to happen after window is trashed as the driver might have a hook registered for the window destruction + instance.vk.vkDestroySurfaceKHR(instance.surface, nil) + instance.surface.reset() + instance.vk.vkDestroyInstance(nil) + instance.vk.reset() + +const LEVEL_MAPPING = { + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: lvlDebug, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: lvlInfo, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: lvlWarn, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: lvlError, +}.toTable + +proc defaultDebugCallback( + messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, + messageTypes: VkDebugUtilsMessageTypeFlagsEXT, + pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT, + userData: pointer +): VkBool32 {.cdecl.} = + + log LEVEL_MAPPING[messageSeverity], &"{toEnums messageTypes}: {pCallbackData.pMessage}" + if messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + echo getStackTrace() + quit() + return false + +proc createDebugMessenger*( + instance: Instance, + severityLevels: openArray[VkDebugUtilsMessageSeverityFlagBitsEXT] = @[], + types: openArray[VkDebugUtilsMessageTypeFlagBitsEXT] = @[], + callback: DebugCallback=defaultDebugCallback +): Debugger = + assert instance.vk.valid + result.instance = instance + var severityLevelBits = VkDebugUtilsMessageSeverityFlagBitsEXT.items.toSeq.toBits + var typeBits = VkDebugUtilsMessageTypeFlagBitsEXT.items.toSeq.toBits + if severityLevels.len > 0: + severityLevelBits = toBits severityLevels + if types.len > 0: + typeBits = toBits types + var createInfo = VkDebugUtilsMessengerCreateInfoEXT( + sType: VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + messageSeverity: severityLevelBits, + messageType: typeBits, + pfnUserCallback: callback, + pUserData: nil, + ) + checkVkResult instance.vk.vkCreateDebugUtilsMessengerEXT(addr(createInfo), nil, addr(result.messenger)) + +proc destroy*(debugger: var Debugger) = + assert debugger.messenger.valid + assert debugger.instance.vk.valid + debugger.instance.vk.vkDestroyDebugUtilsMessengerEXT(debugger.messenger, nil) + debugger.messenger.reset() diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/memory.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/memory.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,140 @@ +import std/strformat + +import ../core +import ./device + +type + MemoryHeap = object + size*: uint64 + flags*: seq[VkMemoryHeapFlagBits] + index*: uint32 + MemoryType* = object + heap*: MemoryHeap + flags*: seq[VkMemoryPropertyFlagBits] + index*: uint32 + PhyscialDeviceMemoryProperties = object + heaps*: seq[MemoryHeap] + types*: seq[MemoryType] + DeviceMemory* = object + device*: Device + vk*: VkDeviceMemory + size*: uint64 + memoryType*: MemoryType + case canMap*: bool + of false: discard + of true: data*: pointer + needsFlushing*: bool + MemoryRequirements* = object + size*: uint64 + alignment*: uint64 + memoryTypes*: seq[MemoryType] + +func `$`*(memoryType: MemoryType): string = + &"Memorytype {memoryType.flags} (heap size: {memoryType.heap.size}, heap flags: {memoryType.heap.flags})" + +proc selectBestMemoryType*(types: seq[MemoryType], requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool): MemoryType = + # todo: we assume there is always at least one memory type that is mappable + assert types.len > 0 + var highestRating = 0'f + result = types[0] + for t in types: + var rating = float(t.heap.size) / 1_000_000'f # select biggest heap if all else equal + if requireMappable and VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in t.flags: + rating += 1000 + if preferVRAM and VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT in t.flags: + rating += 500 + if preferAutoFlush and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in t.flags: + rating += 100 + if rating > highestRating: + highestRating = rating + result = t + +proc getMemoryProperties*(physicalDevice: VkPhysicalDevice): PhyscialDeviceMemoryProperties = + var physicalProperties: VkPhysicalDeviceMemoryProperties + vkGetPhysicalDeviceMemoryProperties(physicalDevice, addr physicalProperties) + for i in 0 ..< physicalProperties.memoryHeapCount: + result.heaps.add MemoryHeap( + size: physicalProperties.memoryHeaps[i].size, + flags: toEnums(physicalProperties.memoryHeaps[i].flags), + index: i, + ) + for i in 0 ..< physicalProperties.memoryTypeCount: + result.types.add MemoryType( + heap: result.heaps[physicalProperties.memoryTypes[i].heapIndex], + flags: toEnums(physicalProperties.memoryTypes[i].propertyFlags), + index: i, + ) + +proc allocate*(device: Device, size: uint64, memoryType: MemoryType): DeviceMemory = + assert device.vk.valid + assert size > 0 + result = DeviceMemory( + device: device, + size: size, + memoryType: memoryType, + canMap: VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in memoryType.flags, + needsFlushing: not (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in memoryType.flags), + ) + + var allocationInfo = VkMemoryAllocateInfo( + sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + allocationSize: size, + memoryTypeIndex: result.memoryType.index, + ) + + checkVkResult vkAllocateMemory( + device.vk, + addr allocationInfo, + nil, + addr result.vk + ) + + if result.canMap: + checkVkResult result.device.vk.vkMapMemory( + memory=result.vk, + offset=VkDeviceSize(0), + size=VkDeviceSize(result.size), + flags=VkMemoryMapFlags(0), # unused up to Vulkan 1.3 + ppData=addr(result.data) + ) + +# flush host -> device +proc flush*(memory: DeviceMemory, offset=0'u64, size=0'u64) = + assert memory.device.vk.valid + assert memory.vk.valid + assert memory.needsFlushing + + var actualSize = size + if actualSize == 0: + actualSize = memory.size + var flushrange = VkMappedMemoryRange( + sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + memory: memory.vk, + offset: VkDeviceSize(offset), + size: VkDeviceSize(size) + ) + checkVkResult memory.device.vk.vkFlushMappedMemoryRanges(memoryRangeCount=1, pMemoryRanges=addr(flushrange)) + +# flush device -> host +proc invalidate*(memory: DeviceMemory, offset=0'u64, size=0'u64) = + assert memory.device.vk.valid + assert memory.vk.valid + assert memory.needsFlushing + + var actualSize = size + if actualSize == 0: + actualSize = memory.size + var flushrange = VkMappedMemoryRange( + sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + memory: memory.vk, + offset: VkDeviceSize(offset), + size: VkDeviceSize(size) + ) + checkVkResult memory.device.vk.vkInvalidateMappedMemoryRanges(memoryRangeCount=1, pMemoryRanges=addr(flushrange)) + +proc free*(memory: var DeviceMemory) = + assert memory.device.vk.valid + assert memory.vk.valid + + memory.device.vk.vkFreeMemory(memory.vk, nil) + memory.vk.reset diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/physicaldevice.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/physicaldevice.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,164 @@ +from std/enumerate import enumerate +import std/tables +import std/sequtils + +import ../core +import ./instance + +type + PhysicalDevice* = object + vk*: VkPhysicalDevice + name*: string + devicetype*: VkPhysicalDeviceType + surface*: VkSurfaceKHR + properties*: VkPhysicalDeviceProperties + features*: VkPhysicalDeviceFeatures2 + QueueFamily* = object + device: PhysicalDevice + properties*: VkQueueFamilyProperties + index*: uint32 + flags*: seq[VkQueueFlagBits] + +func `$`*(device: PhysicalDevice): string = + "Physical device: vk=" & $device.vk & ", name=" & $device.name & ", devicetype=" & $device.devicetype + +proc getPhysicalDevices*(instance: Instance): seq[PhysicalDevice] = + assert instance.vk.valid + assert instance.surface.valid + var nDevices: uint32 + checkVkResult vkEnumeratePhysicalDevices(instance.vk, addr(nDevices), nil) + var devices = newSeq[VkPhysicalDevice](nDevices) + checkVkResult vkEnumeratePhysicalDevices(instance.vk, addr(nDevices), devices.toCPointer) + for i in 0 ..< nDevices: + var device = PhysicalDevice(vk: devices[i], surface: instance.surface) + device.vk.vkGetPhysicalDeviceProperties(addr device.properties) + device.features.stype = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 + device.vk.vkGetPhysicalDeviceFeatures2(addr device.features) + device.name = device.properties.deviceName.cleanString() + device.devicetype = device.properties.deviceType + result.add device + +proc getExtensions*(device: PhysicalDevice): seq[string] = + assert device.vk.valid + var extensionCount: uint32 + checkVkResult vkEnumerateDeviceExtensionProperties(device.vk, nil, addr(extensionCount), nil) + if extensionCount > 0: + var extensions = newSeq[VkExtensionProperties](extensionCount) + checkVkResult vkEnumerateDeviceExtensionProperties(device.vk, nil, addr(extensionCount), extensions.toCPointer) + for extension in extensions: + result.add(cleanString(extension.extensionName)) + +proc getSurfaceCapabilities*(device: PhysicalDevice): VkSurfaceCapabilitiesKHR = + assert device.vk.valid + assert device.surface.valid + checkVkResult device.vk.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device.surface, addr(result)) + +proc getSurfaceFormats*(device: PhysicalDevice): seq[VkSurfaceFormatKHR] = + assert device.vk.valid + assert device.surface.valid + var n_formats: uint32 + checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device.vk, device.surface, addr(n_formats), nil) + result = newSeq[VkSurfaceFormatKHR](n_formats) + checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device.vk, device.surface, addr(n_formats), result.toCPointer) + +func filterSurfaceFormat*( + formats: seq[VkSurfaceFormatKHR], + imageFormat = VK_FORMAT_B8G8R8A8_SRGB, + colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR +): VkSurfaceFormatKHR = + for format in formats: + if format.format == imageFormat and format.colorSpace == colorSpace: + return format + +proc filterSurfaceFormat*(device: PhysicalDevice): VkSurfaceFormatKHR = + assert device.vk.valid + assert device.surface.valid + device.getSurfaceFormats().filterSurfaceFormat() + +proc getSurfacePresentModes*(device: PhysicalDevice): seq[VkPresentModeKHR] = + assert device.vk.valid + assert device.surface.valid + var n_modes: uint32 + checkVkResult vkGetPhysicalDeviceSurfacePresentModesKHR(device.vk, device.surface, addr(n_modes), nil) + result = newSeq[VkPresentModeKHR](n_modes) + checkVkResult vkGetPhysicalDeviceSurfacePresentModesKHR(device.vk, device.surface, addr(n_modes), result.toCPointer) + +proc getQueueFamilies*(device: PhysicalDevice): seq[QueueFamily] = + assert device.vk.valid + var nQueuefamilies: uint32 + vkGetPhysicalDeviceQueueFamilyProperties(device.vk, addr nQueuefamilies, nil) + var queuFamilies = newSeq[VkQueueFamilyProperties](nQueuefamilies) + vkGetPhysicalDeviceQueueFamilyProperties(device.vk, addr nQueuefamilies , queuFamilies.toCPointer) + for i in 0 ..< nQueuefamilies: + result.add QueueFamily( + device: device, + properties: queuFamilies[i], + index: i, + flags: queuFamilies[i].queueFlags.toEnums, + ) + +proc canDoGraphics*(family: QueueFamily): bool = + VK_QUEUE_GRAPHICS_BIT in family.flags + +proc canDoPresentation*(family: QueueFamily, surface: VkSurfaceKHR): bool = + assert surface.valid + var presentation = VkBool32(false) + checkVkResult vkGetPhysicalDeviceSurfaceSupportKHR(family.device.vk, family.index, surface, addr presentation) + return bool(presentation) + +proc canDoTransfer*(family: QueueFamily): bool = + VK_QUEUE_TRANSFER_BIT in family.flags + +proc filterForGraphicsPresentationQueues*(device: PhysicalDevice): seq[QueueFamily] = + var canDoGraphics = false + var canDoPresentation = false + var queues: Table[uint32, QueueFamily] + for family in device.getQueueFamilies(): + if family.canDoGraphics: + queues[family.index] = family + canDoGraphics = true + if family.canDoPresentation(device.surface): + queues[family.index] = family + canDoPresentation = true + if canDoGraphics and canDoPresentation: + return queues.values.toSeq + +proc filterGraphics(families: seq[QueueFamily]): seq[QueueFamily] = + for family in families: + if family.canDoGraphics: + result.add family + +proc filterPresentation(families: seq[QueueFamily], surface: VkSurfaceKHR): seq[QueueFamily] = + assert surface.valid + for family in families: + if family.canDoPresentation(surface): + result.add family + +proc rateGraphics*(device: PhysicalDevice): float = + assert device.vk.valid + assert device.surface.valid + if device.getQueueFamilies().filterGraphics().filterPresentation(device.surface).len == 0: + return -1 + if not ("VK_KHR_swapchain" in device.getExtensions()): + return -1 + const deviceTypeMap = [ + VK_PHYSICAL_DEVICE_TYPE_OTHER, + VK_PHYSICAL_DEVICE_TYPE_CPU, + VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU, + VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, + VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, + ] + for (i, devicetype) in enumerate(deviceTypeMap): + if device.devicetype == devicetype: + result = float(i) + +proc filterBestGraphics*(devices: seq[PhysicalDevice]): PhysicalDevice = + var bestVal = -1'f + for device in devices: + assert device.vk.valid + assert device.surface.valid + let rating = device.rateGraphics() + if rating > bestVal: + bestVal = rating + result = device + assert bestVal >= 0 diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/pipeline.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/pipeline.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,203 @@ +import std/tables +import std/sequtils +import std/strformat + +import ../core +import ./device +import ./descriptor +import ./shader +import ./buffer +import ./image + +type + ShaderPipeline* = object + device*: Device + vk*: VkPipeline + layout*: VkPipelineLayout + shaderConfiguration*: ShaderConfiguration + shaderModules*: (ShaderModule, ShaderModule) + descriptorSetLayout*: DescriptorSetLayout + +func inputs*(pipeline: ShaderPipeline): seq[ShaderAttribute] = + pipeline.shaderConfiguration.inputs + +func uniforms*(pipeline: ShaderPipeline): seq[ShaderAttribute] = + pipeline.shaderConfiguration.uniforms + +func samplers*(pipeline: ShaderPipeline): seq[ShaderAttribute] = + pipeline.shaderConfiguration.samplers + +proc setupDescriptors*(pipeline: ShaderPipeline, descriptorPool: DescriptorPool, buffers: seq[Buffer], textures: var Table[string, seq[VulkanTexture]], inFlightFrames: int, emptyTexture: VulkanTexture): seq[DescriptorSet] = + assert pipeline.vk.valid + assert buffers.len == 0 or buffers.len == inFlightFrames # need to guard against this in case we have no uniforms, then we also create no buffers + + result = descriptorPool.allocateDescriptorSet(pipeline.descriptorSetLayout, inFlightFrames) + + for i in 0 ..< inFlightFrames: + var offset = 0 + # first descriptor is always uniform for globals, match should be better somehow + for descriptor in result[i].layout.descriptors.mitems: + if descriptor.thetype == Uniform and buffers.len > 0: + let size = descriptor.size + descriptor.buffer = buffers[i] + descriptor.offset = offset + descriptor.size = size + offset += size + elif descriptor.thetype == ImageSampler: + if not (descriptor.name in textures): + raise newException(Exception, &"Missing shader texture in scene: {descriptor.name}, available are {textures.keys.toSeq}") + + for textureIndex in 0 ..< int(descriptor.count): + if textureIndex < textures[descriptor.name].len: + descriptor.imageviews.add textures[descriptor.name][textureIndex].imageView + descriptor.samplers.add textures[descriptor.name][textureIndex].sampler + else: + descriptor.imageviews.add emptyTexture.imageView + descriptor.samplers.add emptyTexture.sampler + +proc createPipeline*(device: Device, renderPass: VkRenderPass, shaderConfiguration: ShaderConfiguration, inFlightFrames: int, subpass = 0'u32, backFaceCulling=true): ShaderPipeline = + assert renderPass.valid + assert device.vk.valid + + result.device = device + result.shaderModules = device.createShaderModules(shaderConfiguration) + result.shaderConfiguration = shaderConfiguration + + var descriptors: seq[Descriptor] + if result.shaderConfiguration.uniforms.len > 0: + descriptors.add Descriptor( + name: "Uniforms", + thetype: Uniform, + count: 1, + stages: @[VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT], + size: result.shaderConfiguration.uniforms.size(), + ) + for sampler in result.shaderConfiguration.samplers: + descriptors.add Descriptor( + name: sampler.name, + thetype: ImageSampler, + count: (if sampler.arrayCount == 0: 1 else: sampler.arrayCount), + stages: @[VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT], + ) + result.descriptorSetLayout = device.createDescriptorSetLayout(descriptors) + + # TODO: Push constants + # var pushConstant = VkPushConstantRange( + # stageFlags: toBits shaderStage, + # offset: 0, + # size: 0, + # ) + var descriptorSetLayouts: seq[VkDescriptorSetLayout] = @[result.descriptorSetLayout.vk] + # var pushConstants: seq[VkPushConstantRange] = @[pushConstant] + var pipelineLayoutInfo = VkPipelineLayoutCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + setLayoutCount: uint32(descriptorSetLayouts.len), + pSetLayouts: descriptorSetLayouts.toCPointer, + # pushConstantRangeCount: uint32(pushConstants.len), + # pPushConstantRanges: pushConstants.toCPointer, + ) + checkVkResult vkCreatePipelineLayout(device.vk, addr(pipelineLayoutInfo), nil, addr(result.layout)) + + var + bindings: seq[VkVertexInputBindingDescription] + attributes: seq[VkVertexInputAttributeDescription] + vertexInputInfo = result.shaderConfiguration.getVertexInputInfo(bindings, attributes) + inputAssembly = VkPipelineInputAssemblyStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + topology: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + primitiveRestartEnable: VK_FALSE, + ) + viewportState = VkPipelineViewportStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + viewportCount: 1, + scissorCount: 1, + ) + rasterizer = VkPipelineRasterizationStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + depthClampEnable: VK_FALSE, + rasterizerDiscardEnable: VK_FALSE, + polygonMode: VK_POLYGON_MODE_FILL, + lineWidth: 1.0, + cullMode: if backFaceCulling: toBits [VK_CULL_MODE_BACK_BIT] else: VkCullModeFlags(0), + frontFace: VK_FRONT_FACE_CLOCKWISE, + depthBiasEnable: VK_FALSE, + depthBiasConstantFactor: 0.0, + depthBiasClamp: 0.0, + depthBiasSlopeFactor: 0.0, + ) + multisampling = VkPipelineMultisampleStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + sampleShadingEnable: VK_FALSE, + rasterizationSamples: VK_SAMPLE_COUNT_1_BIT, + minSampleShading: 1.0, + pSampleMask: nil, + alphaToCoverageEnable: VK_FALSE, + alphaToOneEnable: VK_FALSE, + ) + colorBlendAttachment = VkPipelineColorBlendAttachmentState( + colorWriteMask: toBits [VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, VK_COLOR_COMPONENT_A_BIT], + blendEnable: VK_TRUE, + srcColorBlendFactor: VK_BLEND_FACTOR_SRC_ALPHA, + dstColorBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + colorBlendOp: VK_BLEND_OP_ADD, + srcAlphaBlendFactor: VK_BLEND_FACTOR_ONE, + dstAlphaBlendFactor: VK_BLEND_FACTOR_ZERO, + alphaBlendOp: VK_BLEND_OP_ADD, + ) + colorBlending = VkPipelineColorBlendStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + logicOpEnable: false, + attachmentCount: 1, + pAttachments: addr(colorBlendAttachment), + ) + dynamicStates = @[VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR] + dynamicState = VkPipelineDynamicStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + dynamicStateCount: uint32(dynamicStates.len), + pDynamicStates: dynamicStates.toCPointer, + ) + stages = @[result.shaderModules[0].getPipelineInfo(), result.shaderModules[1].getPipelineInfo()] + createInfo = VkGraphicsPipelineCreateInfo( + sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + stageCount: uint32(stages.len), + pStages: stages.toCPointer, + pVertexInputState: addr(vertexInputInfo), + pInputAssemblyState: addr(inputAssembly), + pViewportState: addr(viewportState), + pRasterizationState: addr(rasterizer), + pMultisampleState: addr(multisampling), + pDepthStencilState: nil, + pColorBlendState: addr(colorBlending), + pDynamicState: addr(dynamicState), + layout: result.layout, + renderPass: renderPass, + subpass: subpass, + basePipelineHandle: VkPipeline(0), + basePipelineIndex: -1, + ) + checkVkResult vkCreateGraphicsPipelines( + device.vk, + VkPipelineCache(0), + 1, + addr(createInfo), + nil, + addr(result.vk) + ) + + discard result.uniforms # just for assertion + + +proc destroy*(pipeline: var ShaderPipeline) = + assert pipeline.device.vk.valid + assert pipeline.vk.valid + assert pipeline.layout.valid + assert pipeline.descriptorSetLayout.vk.valid + + pipeline.shaderModules[0].destroy() + pipeline.shaderModules[1].destroy() + pipeline.descriptorSetLayout.destroy() + pipeline.device.vk.vkDestroyPipelineLayout(pipeline.layout, nil) + pipeline.device.vk.vkDestroyPipeline(pipeline.vk, nil) + pipeline.descriptorSetLayout.reset() + pipeline.layout.reset() + pipeline.vk.reset() diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/android.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/android.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,86 @@ +type + VkAndroidSurfaceCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkAndroidSurfaceCreateFlagsKHR + window*: ptr ANativeWindow + VkNativeBufferUsage2ANDROID* = object + consumer*: uint64 + producer*: uint64 + VkNativeBufferANDROID* = object + sType*: VkStructureType + pNext*: pointer + handle*: pointer + stride*: cint + format*: cint + usage*: cint + usage2*: VkNativeBufferUsage2ANDROID + VkSwapchainImageCreateInfoANDROID* = object + sType*: VkStructureType + pNext*: pointer + usage*: VkSwapchainImageUsageFlagsANDROID + VkPhysicalDevicePresentationPropertiesANDROID* = object + sType*: VkStructureType + pNext*: pointer + sharedImage*: VkBool32 + VkImportAndroidHardwareBufferInfoANDROID* = object + sType*: VkStructureType + pNext*: pointer + buffer*: ptr AHardwareBuffer + VkAndroidHardwareBufferUsageANDROID* = object + sType*: VkStructureType + pNext*: pointer + androidHardwareBufferUsage*: uint64 + VkAndroidHardwareBufferPropertiesANDROID* = object + sType*: VkStructureType + pNext*: pointer + allocationSize*: VkDeviceSize + memoryTypeBits*: uint32 + VkMemoryGetAndroidHardwareBufferInfoANDROID* = object + sType*: VkStructureType + pNext*: pointer + memory*: VkDeviceMemory + VkAndroidHardwareBufferFormatPropertiesANDROID* = object + sType*: VkStructureType + pNext*: pointer + format*: VkFormat + externalFormat*: uint64 + formatFeatures*: VkFormatFeatureFlags + samplerYcbcrConversionComponents*: VkComponentMapping + suggestedYcbcrModel*: VkSamplerYcbcrModelConversion + suggestedYcbcrRange*: VkSamplerYcbcrRange + suggestedXChromaOffset*: VkChromaLocation + suggestedYChromaOffset*: VkChromaLocation + VkExternalFormatANDROID* = object + sType*: VkStructureType + pNext*: pointer + externalFormat*: uint64 + VkAndroidHardwareBufferFormatProperties2ANDROID* = object + sType*: VkStructureType + pNext*: pointer + format*: VkFormat + externalFormat*: uint64 + formatFeatures*: VkFormatFeatureFlags2 + samplerYcbcrConversionComponents*: VkComponentMapping + suggestedYcbcrModel*: VkSamplerYcbcrModelConversion + suggestedYcbcrRange*: VkSamplerYcbcrRange + suggestedXChromaOffset*: VkChromaLocation + suggestedYChromaOffset*: VkChromaLocation +# extension VK_ANDROID_external_memory_android_hardware_buffer +var + vkGetAndroidHardwareBufferPropertiesANDROID*: proc(device: VkDevice, buffer: ptr AHardwareBuffer, pProperties: ptr VkAndroidHardwareBufferPropertiesANDROID): VkResult {.stdcall.} + vkGetMemoryAndroidHardwareBufferANDROID*: proc(device: VkDevice, pInfo: ptr VkMemoryGetAndroidHardwareBufferInfoANDROID, pBuffer: ptr ptr AHardwareBuffer): VkResult {.stdcall.} +proc loadVK_ANDROID_external_memory_android_hardware_buffer*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_1(instance) + loadVK_EXT_queue_family_foreign(instance) + loadVK_VERSION_1_1(instance) + vkGetAndroidHardwareBufferPropertiesANDROID = cast[proc(device: VkDevice, buffer: ptr AHardwareBuffer, pProperties: ptr VkAndroidHardwareBufferPropertiesANDROID): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAndroidHardwareBufferPropertiesANDROID")) + vkGetMemoryAndroidHardwareBufferANDROID = cast[proc(device: VkDevice, pInfo: ptr VkMemoryGetAndroidHardwareBufferInfoANDROID, pBuffer: ptr ptr AHardwareBuffer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryAndroidHardwareBufferANDROID")) + +# extension VK_KHR_android_surface +var + vkCreateAndroidSurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkAndroidSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} +proc loadVK_KHR_android_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateAndroidSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkAndroidSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateAndroidSurfaceKHR")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/directfb.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/directfb.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,17 @@ +type + VkDirectFBSurfaceCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkDirectFBSurfaceCreateFlagsEXT + dfb*: ptr IDirectFB + surface*: ptr IDirectFBSurface + IDirectFB *{.header: "directfb.h".} = object + IDirectFBSurface *{.header: "directfb.h".} = object +# extension VK_EXT_directfb_surface +var + vkCreateDirectFBSurfaceEXT*: proc(instance: VkInstance, pCreateInfo: ptr VkDirectFBSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceDirectFBPresentationSupportEXT*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, dfb: ptr IDirectFB): VkBool32 {.stdcall.} +proc loadVK_EXT_directfb_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateDirectFBSurfaceEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDirectFBSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDirectFBSurfaceEXT")) + vkGetPhysicalDeviceDirectFBPresentationSupportEXT = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, dfb: ptr IDirectFB): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDirectFBPresentationSupportEXT")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/fuchsia.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/fuchsia.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,142 @@ +type + VkImagePipeSurfaceCreateInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkImagePipeSurfaceCreateFlagsFUCHSIA + imagePipeHandle*: zx_handle_t + VkImportMemoryZirconHandleInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + handleType*: VkExternalMemoryHandleTypeFlagBits + handle*: zx_handle_t + VkMemoryZirconHandlePropertiesFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + memoryTypeBits*: uint32 + VkMemoryGetZirconHandleInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + memory*: VkDeviceMemory + handleType*: VkExternalMemoryHandleTypeFlagBits + VkImportSemaphoreZirconHandleInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + flags*: VkSemaphoreImportFlags + handleType*: VkExternalSemaphoreHandleTypeFlagBits + zirconHandle*: zx_handle_t + VkSemaphoreGetZirconHandleInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + handleType*: VkExternalSemaphoreHandleTypeFlagBits + VkImportMemoryBufferCollectionFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + collection*: VkBufferCollectionFUCHSIA + index*: uint32 + VkBufferCollectionImageCreateInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + collection*: VkBufferCollectionFUCHSIA + index*: uint32 + VkBufferCollectionBufferCreateInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + collection*: VkBufferCollectionFUCHSIA + index*: uint32 + VkBufferCollectionCreateInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + collectionToken*: zx_handle_t + VkBufferCollectionPropertiesFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + memoryTypeBits*: uint32 + bufferCount*: uint32 + createInfoIndex*: uint32 + sysmemPixelFormat*: uint64 + formatFeatures*: VkFormatFeatureFlags + sysmemColorSpaceIndex*: VkSysmemColorSpaceFUCHSIA + samplerYcbcrConversionComponents*: VkComponentMapping + suggestedYcbcrModel*: VkSamplerYcbcrModelConversion + suggestedYcbcrRange*: VkSamplerYcbcrRange + suggestedXChromaOffset*: VkChromaLocation + suggestedYChromaOffset*: VkChromaLocation + VkBufferConstraintsInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + createInfo*: VkBufferCreateInfo + requiredFormatFeatures*: VkFormatFeatureFlags + bufferCollectionConstraints*: VkBufferCollectionConstraintsInfoFUCHSIA + VkSysmemColorSpaceFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + colorSpace*: uint32 + VkImageFormatConstraintsInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + imageCreateInfo*: VkImageCreateInfo + requiredFormatFeatures*: VkFormatFeatureFlags + flags*: VkImageFormatConstraintsFlagsFUCHSIA + sysmemPixelFormat*: uint64 + colorSpaceCount*: uint32 + pColorSpaces*: ptr VkSysmemColorSpaceFUCHSIA + VkImageConstraintsInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + formatConstraintsCount*: uint32 + pFormatConstraints*: ptr VkImageFormatConstraintsInfoFUCHSIA + bufferCollectionConstraints*: VkBufferCollectionConstraintsInfoFUCHSIA + flags*: VkImageConstraintsInfoFlagsFUCHSIA + VkBufferCollectionConstraintsInfoFUCHSIA* = object + sType*: VkStructureType + pNext*: pointer + minBufferCount*: uint32 + maxBufferCount*: uint32 + minBufferCountForCamping*: uint32 + minBufferCountForDedicatedSlack*: uint32 + minBufferCountForSharedSlack*: uint32 + zx_handle_t *{.header: "zircon/types.h".} = object +# extension VK_FUCHSIA_external_memory +var + vkGetMemoryZirconHandleFUCHSIA*: proc(device: VkDevice, pGetZirconHandleInfo: ptr VkMemoryGetZirconHandleInfoFUCHSIA, pZirconHandle: ptr zx_handle_t): VkResult {.stdcall.} + vkGetMemoryZirconHandlePropertiesFUCHSIA*: proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, zirconHandle: zx_handle_t, pMemoryZirconHandleProperties: ptr VkMemoryZirconHandlePropertiesFUCHSIA): VkResult {.stdcall.} +proc loadVK_FUCHSIA_external_memory*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_1(instance) + vkGetMemoryZirconHandleFUCHSIA = cast[proc(device: VkDevice, pGetZirconHandleInfo: ptr VkMemoryGetZirconHandleInfoFUCHSIA, pZirconHandle: ptr zx_handle_t): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryZirconHandleFUCHSIA")) + vkGetMemoryZirconHandlePropertiesFUCHSIA = cast[proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, zirconHandle: zx_handle_t, pMemoryZirconHandleProperties: ptr VkMemoryZirconHandlePropertiesFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryZirconHandlePropertiesFUCHSIA")) + +# extension VK_FUCHSIA_external_semaphore +var + vkImportSemaphoreZirconHandleFUCHSIA*: proc(device: VkDevice, pImportSemaphoreZirconHandleInfo: ptr VkImportSemaphoreZirconHandleInfoFUCHSIA): VkResult {.stdcall.} + vkGetSemaphoreZirconHandleFUCHSIA*: proc(device: VkDevice, pGetZirconHandleInfo: ptr VkSemaphoreGetZirconHandleInfoFUCHSIA, pZirconHandle: ptr zx_handle_t): VkResult {.stdcall.} +proc loadVK_FUCHSIA_external_semaphore*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_1(instance) + vkImportSemaphoreZirconHandleFUCHSIA = cast[proc(device: VkDevice, pImportSemaphoreZirconHandleInfo: ptr VkImportSemaphoreZirconHandleInfoFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkImportSemaphoreZirconHandleFUCHSIA")) + vkGetSemaphoreZirconHandleFUCHSIA = cast[proc(device: VkDevice, pGetZirconHandleInfo: ptr VkSemaphoreGetZirconHandleInfoFUCHSIA, pZirconHandle: ptr zx_handle_t): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSemaphoreZirconHandleFUCHSIA")) + +# extension VK_FUCHSIA_buffer_collection +var + vkCreateBufferCollectionFUCHSIA*: proc(device: VkDevice, pCreateInfo: ptr VkBufferCollectionCreateInfoFUCHSIA, pAllocator: ptr VkAllocationCallbacks, pCollection: ptr VkBufferCollectionFUCHSIA): VkResult {.stdcall.} + vkSetBufferCollectionImageConstraintsFUCHSIA*: proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pImageConstraintsInfo: ptr VkImageConstraintsInfoFUCHSIA): VkResult {.stdcall.} + vkSetBufferCollectionBufferConstraintsFUCHSIA*: proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pBufferConstraintsInfo: ptr VkBufferConstraintsInfoFUCHSIA): VkResult {.stdcall.} + vkDestroyBufferCollectionFUCHSIA*: proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetBufferCollectionPropertiesFUCHSIA*: proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pProperties: ptr VkBufferCollectionPropertiesFUCHSIA): VkResult {.stdcall.} +proc loadVK_FUCHSIA_buffer_collection*(instance: VkInstance) = + loadVK_FUCHSIA_external_memory(instance) + loadVK_VERSION_1_1(instance) + vkCreateBufferCollectionFUCHSIA = cast[proc(device: VkDevice, pCreateInfo: ptr VkBufferCollectionCreateInfoFUCHSIA, pAllocator: ptr VkAllocationCallbacks, pCollection: ptr VkBufferCollectionFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateBufferCollectionFUCHSIA")) + vkSetBufferCollectionImageConstraintsFUCHSIA = cast[proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pImageConstraintsInfo: ptr VkImageConstraintsInfoFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetBufferCollectionImageConstraintsFUCHSIA")) + vkSetBufferCollectionBufferConstraintsFUCHSIA = cast[proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pBufferConstraintsInfo: ptr VkBufferConstraintsInfoFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetBufferCollectionBufferConstraintsFUCHSIA")) + vkDestroyBufferCollectionFUCHSIA = cast[proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyBufferCollectionFUCHSIA")) + vkGetBufferCollectionPropertiesFUCHSIA = cast[proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pProperties: ptr VkBufferCollectionPropertiesFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferCollectionPropertiesFUCHSIA")) + +# extension VK_FUCHSIA_imagepipe_surface +var + vkCreateImagePipeSurfaceFUCHSIA*: proc(instance: VkInstance, pCreateInfo: ptr VkImagePipeSurfaceCreateInfoFUCHSIA, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} +proc loadVK_FUCHSIA_imagepipe_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateImagePipeSurfaceFUCHSIA = cast[proc(instance: VkInstance, pCreateInfo: ptr VkImagePipeSurfaceCreateInfoFUCHSIA, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateImagePipeSurfaceFUCHSIA")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/ggp.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/ggp.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,22 @@ +type + VkStreamDescriptorSurfaceCreateInfoGGP* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkStreamDescriptorSurfaceCreateFlagsGGP + streamDescriptor*: GgpStreamDescriptor + VkPresentFrameTokenGGP* = object + sType*: VkStructureType + pNext*: pointer + frameToken*: GgpFrameToken + GgpStreamDescriptor *{.header: "ggp_c/vulkan_types.h".} = object + GgpFrameToken *{.header: "ggp_c/vulkan_types.h".} = object +# extension VK_GGP_stream_descriptor_surface +var + vkCreateStreamDescriptorSurfaceGGP*: proc(instance: VkInstance, pCreateInfo: ptr VkStreamDescriptorSurfaceCreateInfoGGP, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} +proc loadVK_GGP_stream_descriptor_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateStreamDescriptorSurfaceGGP = cast[proc(instance: VkInstance, pCreateInfo: ptr VkStreamDescriptorSurfaceCreateInfoGGP, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateStreamDescriptorSurfaceGGP")) + +proc loadVK_GGP_frame_token*(instance: VkInstance) = + loadVK_KHR_swapchain(instance) + loadVK_GGP_stream_descriptor_surface(instance) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/ios.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/ios.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,12 @@ +type + VkIOSSurfaceCreateInfoMVK* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkIOSSurfaceCreateFlagsMVK + pView*: pointer +# extension VK_MVK_ios_surface +var + vkCreateIOSSurfaceMVK*: proc(instance: VkInstance, pCreateInfo: ptr VkIOSSurfaceCreateInfoMVK, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} +proc loadVK_MVK_ios_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateIOSSurfaceMVK = cast[proc(instance: VkInstance, pCreateInfo: ptr VkIOSSurfaceCreateInfoMVK, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateIOSSurfaceMVK")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/macos.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/macos.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,12 @@ +type + VkMacOSSurfaceCreateInfoMVK* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkMacOSSurfaceCreateFlagsMVK + pView*: pointer +# extension VK_MVK_macos_surface +var + vkCreateMacOSSurfaceMVK*: proc(instance: VkInstance, pCreateInfo: ptr VkMacOSSurfaceCreateInfoMVK, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} +proc loadVK_MVK_macos_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateMacOSSurfaceMVK = cast[proc(instance: VkInstance, pCreateInfo: ptr VkMacOSSurfaceCreateInfoMVK, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/metal.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/metal.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,75 @@ +type + VkMetalSurfaceCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkMetalSurfaceCreateFlagsEXT + pLayer*: ptr CAMetalLayer + VkExportMetalObjectCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + exportObjectType*: VkExportMetalObjectTypeFlagBitsEXT + VkExportMetalObjectsInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + VkExportMetalDeviceInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + mtlDevice*: MTLDevice_id + VkExportMetalCommandQueueInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + queue*: VkQueue + mtlCommandQueue*: MTLCommandQueue_id + VkExportMetalBufferInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + memory*: VkDeviceMemory + mtlBuffer*: MTLBuffer_id + VkImportMetalBufferInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + mtlBuffer*: MTLBuffer_id + VkExportMetalTextureInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + image*: VkImage + imageView*: VkImageView + bufferView*: VkBufferView + plane*: VkImageAspectFlagBits + mtlTexture*: MTLTexture_id + VkImportMetalTextureInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + plane*: VkImageAspectFlagBits + mtlTexture*: MTLTexture_id + VkExportMetalIOSurfaceInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + image*: VkImage + ioSurface*: IOSurfaceRef + VkImportMetalIOSurfaceInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + ioSurface*: IOSurfaceRef + VkExportMetalSharedEventInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + event*: VkEvent + mtlSharedEvent*: MTLSharedEvent_id + VkImportMetalSharedEventInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + mtlSharedEvent*: MTLSharedEvent_id +# extension VK_EXT_metal_objects +var + vkExportMetalObjectsEXT*: proc(device: VkDevice, pMetalObjectsInfo: ptr VkExportMetalObjectsInfoEXT): void {.stdcall.} +proc loadVK_EXT_metal_objects*(instance: VkInstance) = + vkExportMetalObjectsEXT = cast[proc(device: VkDevice, pMetalObjectsInfo: ptr VkExportMetalObjectsInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkExportMetalObjectsEXT")) + +# extension VK_EXT_metal_surface +var + vkCreateMetalSurfaceEXT*: proc(instance: VkInstance, pCreateInfo: ptr VkMetalSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} +proc loadVK_EXT_metal_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateMetalSurfaceEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkMetalSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/provisional.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/provisional.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,581 @@ +type + VkPhysicalDevicePortabilitySubsetFeaturesKHR* = object + sType*: VkStructureType + pNext*: pointer + constantAlphaColorBlendFactors*: VkBool32 + events*: VkBool32 + imageViewFormatReinterpretation*: VkBool32 + imageViewFormatSwizzle*: VkBool32 + imageView2DOn3DImage*: VkBool32 + multisampleArrayImage*: VkBool32 + mutableComparisonSamplers*: VkBool32 + pointPolygons*: VkBool32 + samplerMipLodBias*: VkBool32 + separateStencilMaskRef*: VkBool32 + shaderSampleRateInterpolationFunctions*: VkBool32 + tessellationIsolines*: VkBool32 + tessellationPointMode*: VkBool32 + triangleFans*: VkBool32 + vertexAttributeAccessBeyondStride*: VkBool32 + VkPhysicalDevicePortabilitySubsetPropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + minVertexInputBindingStrideAlignment*: uint32 + VkQueueFamilyVideoPropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + videoCodecOperations*: VkVideoCodecOperationFlagsKHR + VkQueueFamilyQueryResultStatusPropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + queryResultStatusSupport*: VkBool32 + VkVideoProfileListInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + profileCount*: uint32 + pProfiles*: ptr VkVideoProfileInfoKHR + VkPhysicalDeviceVideoFormatInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + imageUsage*: VkImageUsageFlags + VkVideoFormatPropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + format*: VkFormat + componentMapping*: VkComponentMapping + imageCreateFlags*: VkImageCreateFlags + imageType*: VkImageType + imageTiling*: VkImageTiling + imageUsageFlags*: VkImageUsageFlags + VkVideoProfileInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + videoCodecOperation*: VkVideoCodecOperationFlagBitsKHR + chromaSubsampling*: VkVideoChromaSubsamplingFlagsKHR + lumaBitDepth*: VkVideoComponentBitDepthFlagsKHR + chromaBitDepth*: VkVideoComponentBitDepthFlagsKHR + VkVideoCapabilitiesKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoCapabilityFlagsKHR + minBitstreamBufferOffsetAlignment*: VkDeviceSize + minBitstreamBufferSizeAlignment*: VkDeviceSize + pictureAccessGranularity*: VkExtent2D + minCodedExtent*: VkExtent2D + maxCodedExtent*: VkExtent2D + maxDpbSlots*: uint32 + maxActiveReferencePictures*: uint32 + stdHeaderVersion*: VkExtensionProperties + VkVideoSessionMemoryRequirementsKHR* = object + sType*: VkStructureType + pNext*: pointer + memoryBindIndex*: uint32 + memoryRequirements*: VkMemoryRequirements + VkBindVideoSessionMemoryInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + memoryBindIndex*: uint32 + memory*: VkDeviceMemory + memoryOffset*: VkDeviceSize + memorySize*: VkDeviceSize + VkVideoPictureResourceInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + codedOffset*: VkOffset2D + codedExtent*: VkExtent2D + baseArrayLayer*: uint32 + imageViewBinding*: VkImageView + VkVideoReferenceSlotInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + slotIndex*: int32 + pPictureResource*: ptr VkVideoPictureResourceInfoKHR + VkVideoDecodeCapabilitiesKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoDecodeCapabilityFlagsKHR + VkVideoDecodeUsageInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + videoUsageHints*: VkVideoDecodeUsageFlagsKHR + VkVideoDecodeInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoDecodeFlagsKHR + srcBuffer*: VkBuffer + srcBufferOffset*: VkDeviceSize + srcBufferRange*: VkDeviceSize + dstPictureResource*: VkVideoPictureResourceInfoKHR + pSetupReferenceSlot*: ptr VkVideoReferenceSlotInfoKHR + referenceSlotCount*: uint32 + pReferenceSlots*: ptr VkVideoReferenceSlotInfoKHR + VkVideoDecodeH264ProfileInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + stdProfileIdc*: StdVideoH264ProfileIdc + pictureLayout*: VkVideoDecodeH264PictureLayoutFlagBitsKHR + VkVideoDecodeH264CapabilitiesKHR* = object + sType*: VkStructureType + pNext*: pointer + maxLevelIdc*: StdVideoH264LevelIdc + fieldOffsetGranularity*: VkOffset2D + VkVideoDecodeH264SessionParametersAddInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + stdSPSCount*: uint32 + pStdSPSs*: ptr StdVideoH264SequenceParameterSet + stdPPSCount*: uint32 + pStdPPSs*: ptr StdVideoH264PictureParameterSet + VkVideoDecodeH264SessionParametersCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + maxStdSPSCount*: uint32 + maxStdPPSCount*: uint32 + pParametersAddInfo*: ptr VkVideoDecodeH264SessionParametersAddInfoKHR + VkVideoDecodeH264PictureInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pStdPictureInfo*: ptr StdVideoDecodeH264PictureInfo + sliceCount*: uint32 + pSliceOffsets*: ptr uint32 + VkVideoDecodeH264DpbSlotInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pStdReferenceInfo*: ptr StdVideoDecodeH264ReferenceInfo + VkVideoDecodeH265ProfileInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + stdProfileIdc*: StdVideoH265ProfileIdc + VkVideoDecodeH265CapabilitiesKHR* = object + sType*: VkStructureType + pNext*: pointer + maxLevelIdc*: StdVideoH265LevelIdc + VkVideoDecodeH265SessionParametersAddInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + stdVPSCount*: uint32 + pStdVPSs*: ptr StdVideoH265VideoParameterSet + stdSPSCount*: uint32 + pStdSPSs*: ptr StdVideoH265SequenceParameterSet + stdPPSCount*: uint32 + pStdPPSs*: ptr StdVideoH265PictureParameterSet + VkVideoDecodeH265SessionParametersCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + maxStdVPSCount*: uint32 + maxStdSPSCount*: uint32 + maxStdPPSCount*: uint32 + pParametersAddInfo*: ptr VkVideoDecodeH265SessionParametersAddInfoKHR + VkVideoDecodeH265PictureInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pStdPictureInfo*: ptr StdVideoDecodeH265PictureInfo + sliceSegmentCount*: uint32 + pSliceSegmentOffsets*: ptr uint32 + VkVideoDecodeH265DpbSlotInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pStdReferenceInfo*: ptr StdVideoDecodeH265ReferenceInfo + VkVideoSessionCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + queueFamilyIndex*: uint32 + flags*: VkVideoSessionCreateFlagsKHR + pVideoProfile*: ptr VkVideoProfileInfoKHR + pictureFormat*: VkFormat + maxCodedExtent*: VkExtent2D + referencePictureFormat*: VkFormat + maxDpbSlots*: uint32 + maxActiveReferencePictures*: uint32 + pStdHeaderVersion*: ptr VkExtensionProperties + VkVideoSessionParametersCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoSessionParametersCreateFlagsKHR + videoSessionParametersTemplate*: VkVideoSessionParametersKHR + videoSession*: VkVideoSessionKHR + VkVideoSessionParametersUpdateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + updateSequenceCount*: uint32 + VkVideoBeginCodingInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoBeginCodingFlagsKHR + videoSession*: VkVideoSessionKHR + videoSessionParameters*: VkVideoSessionParametersKHR + referenceSlotCount*: uint32 + pReferenceSlots*: ptr VkVideoReferenceSlotInfoKHR + VkVideoEndCodingInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoEndCodingFlagsKHR + VkVideoCodingControlInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoCodingControlFlagsKHR + VkVideoEncodeUsageInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + videoUsageHints*: VkVideoEncodeUsageFlagsKHR + videoContentHints*: VkVideoEncodeContentFlagsKHR + tuningMode*: VkVideoEncodeTuningModeKHR + VkVideoEncodeInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoEncodeFlagsKHR + qualityLevel*: uint32 + dstBitstreamBuffer*: VkBuffer + dstBitstreamBufferOffset*: VkDeviceSize + dstBitstreamBufferMaxRange*: VkDeviceSize + srcPictureResource*: VkVideoPictureResourceInfoKHR + pSetupReferenceSlot*: ptr VkVideoReferenceSlotInfoKHR + referenceSlotCount*: uint32 + pReferenceSlots*: ptr VkVideoReferenceSlotInfoKHR + precedingExternallyEncodedBytes*: uint32 + VkVideoEncodeRateControlInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoEncodeRateControlFlagsKHR + rateControlMode*: VkVideoEncodeRateControlModeFlagBitsKHR + layerCount*: uint8 + pLayerConfigs*: ptr VkVideoEncodeRateControlLayerInfoKHR + VkVideoEncodeRateControlLayerInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + averageBitrate*: uint32 + maxBitrate*: uint32 + frameRateNumerator*: uint32 + frameRateDenominator*: uint32 + virtualBufferSizeInMs*: uint32 + initialVirtualBufferSizeInMs*: uint32 + VkVideoEncodeCapabilitiesKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoEncodeCapabilityFlagsKHR + rateControlModes*: VkVideoEncodeRateControlModeFlagsKHR + rateControlLayerCount*: uint8 + qualityLevelCount*: uint8 + inputImageDataFillAlignment*: VkExtent2D + VkVideoEncodeH264CapabilitiesEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoEncodeH264CapabilityFlagsEXT + inputModeFlags*: VkVideoEncodeH264InputModeFlagsEXT + outputModeFlags*: VkVideoEncodeH264OutputModeFlagsEXT + maxPPictureL0ReferenceCount*: uint8 + maxBPictureL0ReferenceCount*: uint8 + maxL1ReferenceCount*: uint8 + motionVectorsOverPicBoundariesFlag*: VkBool32 + maxBytesPerPicDenom*: uint32 + maxBitsPerMbDenom*: uint32 + log2MaxMvLengthHorizontal*: uint32 + log2MaxMvLengthVertical*: uint32 + VkVideoEncodeH264SessionParametersAddInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + stdSPSCount*: uint32 + pStdSPSs*: ptr StdVideoH264SequenceParameterSet + stdPPSCount*: uint32 + pStdPPSs*: ptr StdVideoH264PictureParameterSet + VkVideoEncodeH264SessionParametersCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + maxStdSPSCount*: uint32 + maxStdPPSCount*: uint32 + pParametersAddInfo*: ptr VkVideoEncodeH264SessionParametersAddInfoEXT + VkVideoEncodeH264DpbSlotInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + slotIndex*: int8 + pStdReferenceInfo*: ptr StdVideoEncodeH264ReferenceInfo + VkVideoEncodeH264VclFrameInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + pReferenceFinalLists*: ptr VkVideoEncodeH264ReferenceListsInfoEXT + naluSliceEntryCount*: uint32 + pNaluSliceEntries*: ptr VkVideoEncodeH264NaluSliceInfoEXT + pCurrentPictureInfo*: ptr StdVideoEncodeH264PictureInfo + VkVideoEncodeH264ReferenceListsInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + referenceList0EntryCount*: uint8 + pReferenceList0Entries*: ptr VkVideoEncodeH264DpbSlotInfoEXT + referenceList1EntryCount*: uint8 + pReferenceList1Entries*: ptr VkVideoEncodeH264DpbSlotInfoEXT + pMemMgmtCtrlOperations*: ptr StdVideoEncodeH264RefMemMgmtCtrlOperations + VkVideoEncodeH264EmitPictureParametersInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + spsId*: uint8 + emitSpsEnable*: VkBool32 + ppsIdEntryCount*: uint32 + ppsIdEntries*: ptr uint8 + VkVideoEncodeH264ProfileInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + stdProfileIdc*: StdVideoH264ProfileIdc + VkVideoEncodeH264NaluSliceInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + mbCount*: uint32 + pReferenceFinalLists*: ptr VkVideoEncodeH264ReferenceListsInfoEXT + pSliceHeaderStd*: ptr StdVideoEncodeH264SliceHeader + VkVideoEncodeH264RateControlInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + gopFrameCount*: uint32 + idrPeriod*: uint32 + consecutiveBFrameCount*: uint32 + rateControlStructure*: VkVideoEncodeH264RateControlStructureEXT + temporalLayerCount*: uint8 + VkVideoEncodeH264QpEXT* = object + qpI*: int32 + qpP*: int32 + qpB*: int32 + VkVideoEncodeH264FrameSizeEXT* = object + frameISize*: uint32 + framePSize*: uint32 + frameBSize*: uint32 + VkVideoEncodeH264RateControlLayerInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + temporalLayerId*: uint8 + useInitialRcQp*: VkBool32 + initialRcQp*: VkVideoEncodeH264QpEXT + useMinQp*: VkBool32 + minQp*: VkVideoEncodeH264QpEXT + useMaxQp*: VkBool32 + maxQp*: VkVideoEncodeH264QpEXT + useMaxFrameSize*: VkBool32 + maxFrameSize*: VkVideoEncodeH264FrameSizeEXT + VkVideoEncodeH265CapabilitiesEXT* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkVideoEncodeH265CapabilityFlagsEXT + inputModeFlags*: VkVideoEncodeH265InputModeFlagsEXT + outputModeFlags*: VkVideoEncodeH265OutputModeFlagsEXT + ctbSizes*: VkVideoEncodeH265CtbSizeFlagsEXT + transformBlockSizes*: VkVideoEncodeH265TransformBlockSizeFlagsEXT + maxPPictureL0ReferenceCount*: uint8 + maxBPictureL0ReferenceCount*: uint8 + maxL1ReferenceCount*: uint8 + maxSubLayersCount*: uint8 + minLog2MinLumaCodingBlockSizeMinus3*: uint8 + maxLog2MinLumaCodingBlockSizeMinus3*: uint8 + minLog2MinLumaTransformBlockSizeMinus2*: uint8 + maxLog2MinLumaTransformBlockSizeMinus2*: uint8 + minMaxTransformHierarchyDepthInter*: uint8 + maxMaxTransformHierarchyDepthInter*: uint8 + minMaxTransformHierarchyDepthIntra*: uint8 + maxMaxTransformHierarchyDepthIntra*: uint8 + maxDiffCuQpDeltaDepth*: uint8 + minMaxNumMergeCand*: uint8 + maxMaxNumMergeCand*: uint8 + VkVideoEncodeH265SessionParametersAddInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + stdVPSCount*: uint32 + pStdVPSs*: ptr StdVideoH265VideoParameterSet + stdSPSCount*: uint32 + pStdSPSs*: ptr StdVideoH265SequenceParameterSet + stdPPSCount*: uint32 + pStdPPSs*: ptr StdVideoH265PictureParameterSet + VkVideoEncodeH265SessionParametersCreateInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + maxStdVPSCount*: uint32 + maxStdSPSCount*: uint32 + maxStdPPSCount*: uint32 + pParametersAddInfo*: ptr VkVideoEncodeH265SessionParametersAddInfoEXT + VkVideoEncodeH265VclFrameInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + pReferenceFinalLists*: ptr VkVideoEncodeH265ReferenceListsInfoEXT + naluSliceSegmentEntryCount*: uint32 + pNaluSliceSegmentEntries*: ptr VkVideoEncodeH265NaluSliceSegmentInfoEXT + pCurrentPictureInfo*: ptr StdVideoEncodeH265PictureInfo + VkVideoEncodeH265EmitPictureParametersInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + vpsId*: uint8 + spsId*: uint8 + emitVpsEnable*: VkBool32 + emitSpsEnable*: VkBool32 + ppsIdEntryCount*: uint32 + ppsIdEntries*: ptr uint8 + VkVideoEncodeH265NaluSliceSegmentInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + ctbCount*: uint32 + pReferenceFinalLists*: ptr VkVideoEncodeH265ReferenceListsInfoEXT + pSliceSegmentHeaderStd*: ptr StdVideoEncodeH265SliceSegmentHeader + VkVideoEncodeH265RateControlInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + gopFrameCount*: uint32 + idrPeriod*: uint32 + consecutiveBFrameCount*: uint32 + rateControlStructure*: VkVideoEncodeH265RateControlStructureEXT + subLayerCount*: uint8 + VkVideoEncodeH265QpEXT* = object + qpI*: int32 + qpP*: int32 + qpB*: int32 + VkVideoEncodeH265FrameSizeEXT* = object + frameISize*: uint32 + framePSize*: uint32 + frameBSize*: uint32 + VkVideoEncodeH265RateControlLayerInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + temporalId*: uint8 + useInitialRcQp*: VkBool32 + initialRcQp*: VkVideoEncodeH265QpEXT + useMinQp*: VkBool32 + minQp*: VkVideoEncodeH265QpEXT + useMaxQp*: VkBool32 + maxQp*: VkVideoEncodeH265QpEXT + useMaxFrameSize*: VkBool32 + maxFrameSize*: VkVideoEncodeH265FrameSizeEXT + VkVideoEncodeH265ProfileInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + stdProfileIdc*: StdVideoH265ProfileIdc + VkVideoEncodeH265DpbSlotInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + slotIndex*: int8 + pStdReferenceInfo*: ptr StdVideoEncodeH265ReferenceInfo + VkVideoEncodeH265ReferenceListsInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + referenceList0EntryCount*: uint8 + pReferenceList0Entries*: ptr VkVideoEncodeH265DpbSlotInfoEXT + referenceList1EntryCount*: uint8 + pReferenceList1Entries*: ptr VkVideoEncodeH265DpbSlotInfoEXT + pReferenceModifications*: ptr StdVideoEncodeH265ReferenceModifications + StdVideoH264ProfileIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264LevelIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264ChromaFormatIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264PocType *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264SpsFlags *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264ScalingLists *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264SequenceParameterSetVui *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264AspectRatioIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264HrdParameters *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264SpsVuiFlags *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264WeightedBipredIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264PpsFlags *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264SliceType *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264CabacInitIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264DisableDeblockingFilterIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264PictureType *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264ModificationOfPicNumsIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264MemMgmtControlOp *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoDecodeH264PictureInfo *{.header: "vk_video/vulkan_video_codec_h264std_decode.h".} = object + StdVideoDecodeH264ReferenceInfo *{.header: "vk_video/vulkan_video_codec_h264std_decode.h".} = object + StdVideoDecodeH264PictureInfoFlags *{.header: "vk_video/vulkan_video_codec_h264std_decode.h".} = object + StdVideoDecodeH264ReferenceInfoFlags *{.header: "vk_video/vulkan_video_codec_h264std_decode.h".} = object + StdVideoH264SequenceParameterSet *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH264PictureParameterSet *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object + StdVideoH265ProfileIdc *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265VideoParameterSet *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265SequenceParameterSet *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265PictureParameterSet *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265DecPicBufMgr *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265HrdParameters *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265VpsFlags *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265LevelIdc *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265SpsFlags *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265ScalingLists *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265SequenceParameterSetVui *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265PredictorPaletteEntries *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265PpsFlags *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265SubLayerHrdParameters *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265HrdFlags *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265SpsVuiFlags *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265SliceType *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoH265PictureType *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object + StdVideoDecodeH265PictureInfo *{.header: "vk_video/vulkan_video_codec_h265std_decode.h".} = object + StdVideoDecodeH265ReferenceInfo *{.header: "vk_video/vulkan_video_codec_h265std_decode.h".} = object + StdVideoDecodeH265PictureInfoFlags *{.header: "vk_video/vulkan_video_codec_h265std_decode.h".} = object + StdVideoDecodeH265ReferenceInfoFlags *{.header: "vk_video/vulkan_video_codec_h265std_decode.h".} = object + StdVideoEncodeH264SliceHeader *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object + StdVideoEncodeH264PictureInfo *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object + StdVideoEncodeH264ReferenceInfo *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object + StdVideoEncodeH264SliceHeaderFlags *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object + StdVideoEncodeH264RefMemMgmtCtrlOperations *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object + StdVideoEncodeH264PictureInfoFlags *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object + StdVideoEncodeH264ReferenceInfoFlags *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object + StdVideoEncodeH264RefMgmtFlags *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object + StdVideoEncodeH264RefListModEntry *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object + StdVideoEncodeH264RefPicMarkingEntry *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object + StdVideoEncodeH265PictureInfoFlags *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object + StdVideoEncodeH265PictureInfo *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object + StdVideoEncodeH265SliceSegmentHeader *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object + StdVideoEncodeH265ReferenceInfo *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object + StdVideoEncodeH265ReferenceModifications *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object + StdVideoEncodeH265SliceSegmentHeaderFlags *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object + StdVideoEncodeH265ReferenceInfoFlags *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object + StdVideoEncodeH265ReferenceModificationFlags *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object +# extension VK_KHR_video_queue +var + vkGetPhysicalDeviceVideoCapabilitiesKHR*: proc(physicalDevice: VkPhysicalDevice, pVideoProfile: ptr VkVideoProfileInfoKHR, pCapabilities: ptr VkVideoCapabilitiesKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceVideoFormatPropertiesKHR*: proc(physicalDevice: VkPhysicalDevice, pVideoFormatInfo: ptr VkPhysicalDeviceVideoFormatInfoKHR, pVideoFormatPropertyCount: ptr uint32, pVideoFormatProperties: ptr VkVideoFormatPropertiesKHR): VkResult {.stdcall.} + vkCreateVideoSessionKHR*: proc(device: VkDevice, pCreateInfo: ptr VkVideoSessionCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pVideoSession: ptr VkVideoSessionKHR): VkResult {.stdcall.} + vkDestroyVideoSessionKHR*: proc(device: VkDevice, videoSession: VkVideoSessionKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkGetVideoSessionMemoryRequirementsKHR*: proc(device: VkDevice, videoSession: VkVideoSessionKHR, pMemoryRequirementsCount: ptr uint32, pMemoryRequirements: ptr VkVideoSessionMemoryRequirementsKHR): VkResult {.stdcall.} + vkBindVideoSessionMemoryKHR*: proc(device: VkDevice, videoSession: VkVideoSessionKHR, bindSessionMemoryInfoCount: uint32, pBindSessionMemoryInfos: ptr VkBindVideoSessionMemoryInfoKHR): VkResult {.stdcall.} + vkCreateVideoSessionParametersKHR*: proc(device: VkDevice, pCreateInfo: ptr VkVideoSessionParametersCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pVideoSessionParameters: ptr VkVideoSessionParametersKHR): VkResult {.stdcall.} + vkUpdateVideoSessionParametersKHR*: proc(device: VkDevice, videoSessionParameters: VkVideoSessionParametersKHR, pUpdateInfo: ptr VkVideoSessionParametersUpdateInfoKHR): VkResult {.stdcall.} + vkDestroyVideoSessionParametersKHR*: proc(device: VkDevice, videoSessionParameters: VkVideoSessionParametersKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} + vkCmdBeginVideoCodingKHR*: proc(commandBuffer: VkCommandBuffer, pBeginInfo: ptr VkVideoBeginCodingInfoKHR): void {.stdcall.} + vkCmdEndVideoCodingKHR*: proc(commandBuffer: VkCommandBuffer, pEndCodingInfo: ptr VkVideoEndCodingInfoKHR): void {.stdcall.} + vkCmdControlVideoCodingKHR*: proc(commandBuffer: VkCommandBuffer, pCodingControlInfo: ptr VkVideoCodingControlInfoKHR): void {.stdcall.} +proc loadVK_KHR_video_queue*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_VERSION_1_3(instance) + vkGetPhysicalDeviceVideoCapabilitiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pVideoProfile: ptr VkVideoProfileInfoKHR, pCapabilities: ptr VkVideoCapabilitiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoCapabilitiesKHR")) + vkGetPhysicalDeviceVideoFormatPropertiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pVideoFormatInfo: ptr VkPhysicalDeviceVideoFormatInfoKHR, pVideoFormatPropertyCount: ptr uint32, pVideoFormatProperties: ptr VkVideoFormatPropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoFormatPropertiesKHR")) + vkCreateVideoSessionKHR = cast[proc(device: VkDevice, pCreateInfo: ptr VkVideoSessionCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pVideoSession: ptr VkVideoSessionKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateVideoSessionKHR")) + vkDestroyVideoSessionKHR = cast[proc(device: VkDevice, videoSession: VkVideoSessionKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyVideoSessionKHR")) + vkGetVideoSessionMemoryRequirementsKHR = cast[proc(device: VkDevice, videoSession: VkVideoSessionKHR, pMemoryRequirementsCount: ptr uint32, pMemoryRequirements: ptr VkVideoSessionMemoryRequirementsKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetVideoSessionMemoryRequirementsKHR")) + vkBindVideoSessionMemoryKHR = cast[proc(device: VkDevice, videoSession: VkVideoSessionKHR, bindSessionMemoryInfoCount: uint32, pBindSessionMemoryInfos: ptr VkBindVideoSessionMemoryInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindVideoSessionMemoryKHR")) + vkCreateVideoSessionParametersKHR = cast[proc(device: VkDevice, pCreateInfo: ptr VkVideoSessionParametersCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pVideoSessionParameters: ptr VkVideoSessionParametersKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateVideoSessionParametersKHR")) + vkUpdateVideoSessionParametersKHR = cast[proc(device: VkDevice, videoSessionParameters: VkVideoSessionParametersKHR, pUpdateInfo: ptr VkVideoSessionParametersUpdateInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkUpdateVideoSessionParametersKHR")) + vkDestroyVideoSessionParametersKHR = cast[proc(device: VkDevice, videoSessionParameters: VkVideoSessionParametersKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyVideoSessionParametersKHR")) + vkCmdBeginVideoCodingKHR = cast[proc(commandBuffer: VkCommandBuffer, pBeginInfo: ptr VkVideoBeginCodingInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginVideoCodingKHR")) + vkCmdEndVideoCodingKHR = cast[proc(commandBuffer: VkCommandBuffer, pEndCodingInfo: ptr VkVideoEndCodingInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndVideoCodingKHR")) + vkCmdControlVideoCodingKHR = cast[proc(commandBuffer: VkCommandBuffer, pCodingControlInfo: ptr VkVideoCodingControlInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdControlVideoCodingKHR")) + +# extension VK_KHR_video_encode_queue +var + vkCmdEncodeVideoKHR*: proc(commandBuffer: VkCommandBuffer, pEncodeInfo: ptr VkVideoEncodeInfoKHR): void {.stdcall.} +proc loadVK_KHR_video_encode_queue*(instance: VkInstance) = + loadVK_KHR_video_queue(instance) + loadVK_VERSION_1_3(instance) + vkCmdEncodeVideoKHR = cast[proc(commandBuffer: VkCommandBuffer, pEncodeInfo: ptr VkVideoEncodeInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEncodeVideoKHR")) + +# extension VK_KHR_video_decode_queue +var + vkCmdDecodeVideoKHR*: proc(commandBuffer: VkCommandBuffer, pDecodeInfo: ptr VkVideoDecodeInfoKHR): void {.stdcall.} +proc loadVK_KHR_video_decode_queue*(instance: VkInstance) = + loadVK_KHR_video_queue(instance) + loadVK_VERSION_1_3(instance) + vkCmdDecodeVideoKHR = cast[proc(commandBuffer: VkCommandBuffer, pDecodeInfo: ptr VkVideoDecodeInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDecodeVideoKHR")) + +proc loadVK_KHR_portability_subset*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + +proc loadVK_EXT_video_encode_h264*(instance: VkInstance) = + loadVK_KHR_video_encode_queue(instance) + +proc loadVK_EXT_video_encode_h265*(instance: VkInstance) = + loadVK_KHR_video_encode_queue(instance) + +proc loadVK_KHR_video_decode_h265*(instance: VkInstance) = + loadVK_KHR_video_decode_queue(instance) + +proc loadVK_KHR_video_decode_h264*(instance: VkInstance) = + loadVK_KHR_video_decode_queue(instance) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/sci.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/sci.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,92 @@ +type + VkExportMemorySciBufInfoNV* = object + sType*: VkStructureType + pNext*: pointer + pAttributes*: NvSciBufAttrList + VkImportMemorySciBufInfoNV* = object + sType*: VkStructureType + pNext*: pointer + handleType*: VkExternalMemoryHandleTypeFlagBits + handle*: NvSciBufObj + VkMemoryGetSciBufInfoNV* = object + sType*: VkStructureType + pNext*: pointer + memory*: VkDeviceMemory + handleType*: VkExternalMemoryHandleTypeFlagBits + VkMemorySciBufPropertiesNV* = object + sType*: VkStructureType + pNext*: pointer + memoryTypeBits*: uint32 + VkPhysicalDeviceExternalMemorySciBufFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + sciBufImport*: VkBool32 + sciBufExport*: VkBool32 + VkPhysicalDeviceExternalSciBufFeaturesNV* = object + VkExportFenceSciSyncInfoNV* = object + sType*: VkStructureType + pNext*: pointer + pAttributes*: NvSciSyncAttrList + VkImportFenceSciSyncInfoNV* = object + sType*: VkStructureType + pNext*: pointer + fence*: VkFence + handleType*: VkExternalFenceHandleTypeFlagBits + handle*: pointer + VkFenceGetSciSyncInfoNV* = object + sType*: VkStructureType + pNext*: pointer + fence*: VkFence + handleType*: VkExternalFenceHandleTypeFlagBits + VkExportSemaphoreSciSyncInfoNV* = object + sType*: VkStructureType + pNext*: pointer + pAttributes*: NvSciSyncAttrList + VkImportSemaphoreSciSyncInfoNV* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + handleType*: VkExternalSemaphoreHandleTypeFlagBits + handle*: pointer + VkSemaphoreGetSciSyncInfoNV* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + handleType*: VkExternalSemaphoreHandleTypeFlagBits + VkSciSyncAttributesInfoNV* = object + sType*: VkStructureType + pNext*: pointer + clientType*: VkSciSyncClientTypeNV + primitiveType*: VkSciSyncPrimitiveTypeNV + VkPhysicalDeviceExternalSciSyncFeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + sciSyncFence*: VkBool32 + sciSyncSemaphore*: VkBool32 + sciSyncImport*: VkBool32 + sciSyncExport*: VkBool32 + VkPhysicalDeviceExternalSciSync2FeaturesNV* = object + sType*: VkStructureType + pNext*: pointer + sciSyncFence*: VkBool32 + sciSyncSemaphore2*: VkBool32 + sciSyncImport*: VkBool32 + sciSyncExport*: VkBool32 + VkSemaphoreSciSyncPoolCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + handle*: NvSciSyncObj + VkSemaphoreSciSyncCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + semaphorePool*: VkSemaphoreSciSyncPoolNV + pFence*: ptr NvSciSyncFence + VkDeviceSemaphoreSciSyncPoolReservationCreateInfoNV* = object + sType*: VkStructureType + pNext*: pointer + semaphoreSciSyncPoolRequestCount*: uint32 + NvSciSyncAttrList *{.header: "nvscisync.h".} = object + NvSciSyncObj *{.header: "nvscisync.h".} = object + NvSciSyncFence *{.header: "nvscisync.h".} = object + NvSciBufAttrList *{.header: "nvscibuf.h".} = object + NvSciBufObj *{.header: "nvscibuf.h".} = object \ No newline at end of file diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/screen.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/screen.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,17 @@ +type + VkScreenSurfaceCreateInfoQNX* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkScreenSurfaceCreateFlagsQNX + context*: ptr screen_context + window*: ptr screen_window + screen_context *{.header: "screen/screen.h".} = object + screen_window *{.header: "screen/screen.h".} = object +# extension VK_QNX_screen_surface +var + vkCreateScreenSurfaceQNX*: proc(instance: VkInstance, pCreateInfo: ptr VkScreenSurfaceCreateInfoQNX, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceScreenPresentationSupportQNX*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, window: ptr screen_window): VkBool32 {.stdcall.} +proc loadVK_QNX_screen_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateScreenSurfaceQNX = cast[proc(instance: VkInstance, pCreateInfo: ptr VkScreenSurfaceCreateInfoQNX, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateScreenSurfaceQNX")) + vkGetPhysicalDeviceScreenPresentationSupportQNX = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, window: ptr screen_window): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceScreenPresentationSupportQNX")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/vi.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/vi.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,12 @@ +type + VkViSurfaceCreateInfoNN* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkViSurfaceCreateFlagsNN + window*: pointer +# extension VK_NN_vi_surface +var + vkCreateViSurfaceNN*: proc(instance: VkInstance, pCreateInfo: ptr VkViSurfaceCreateInfoNN, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} +proc loadVK_NN_vi_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateViSurfaceNN = cast[proc(instance: VkInstance, pCreateInfo: ptr VkViSurfaceCreateInfoNN, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateViSurfaceNN")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/wayland.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/wayland.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,17 @@ +type + VkWaylandSurfaceCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkWaylandSurfaceCreateFlagsKHR + display*: ptr wl_display + surface*: ptr wl_surface + wl_display *{.header: "wayland-client.h".} = object + wl_surface *{.header: "wayland-client.h".} = object +# extension VK_KHR_wayland_surface +var + vkCreateWaylandSurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkWaylandSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceWaylandPresentationSupportKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, display: ptr wl_display): VkBool32 {.stdcall.} +proc loadVK_KHR_wayland_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateWaylandSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkWaylandSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR")) + vkGetPhysicalDeviceWaylandPresentationSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, display: ptr wl_display): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/win32.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/win32.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,193 @@ +type + VkWin32SurfaceCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkWin32SurfaceCreateFlagsKHR + hinstance*: HINSTANCE + hwnd*: HWND + VkImportMemoryWin32HandleInfoNV* = object + sType*: VkStructureType + pNext*: pointer + handleType*: VkExternalMemoryHandleTypeFlagsNV + handle*: HANDLE + VkExportMemoryWin32HandleInfoNV* = object + sType*: VkStructureType + pNext*: pointer + pAttributes*: ptr SECURITY_ATTRIBUTES + dwAccess*: DWORD + VkWin32KeyedMutexAcquireReleaseInfoNV* = object + sType*: VkStructureType + pNext*: pointer + acquireCount*: uint32 + pAcquireSyncs*: ptr VkDeviceMemory + pAcquireKeys*: ptr uint64 + pAcquireTimeoutMilliseconds*: ptr uint32 + releaseCount*: uint32 + pReleaseSyncs*: ptr VkDeviceMemory + pReleaseKeys*: ptr uint64 + VkImportMemoryWin32HandleInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + handleType*: VkExternalMemoryHandleTypeFlagBits + handle*: HANDLE + name*: LPCWSTR + VkExportMemoryWin32HandleInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pAttributes*: ptr SECURITY_ATTRIBUTES + dwAccess*: DWORD + name*: LPCWSTR + VkMemoryWin32HandlePropertiesKHR* = object + sType*: VkStructureType + pNext*: pointer + memoryTypeBits*: uint32 + VkMemoryGetWin32HandleInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + memory*: VkDeviceMemory + handleType*: VkExternalMemoryHandleTypeFlagBits + VkWin32KeyedMutexAcquireReleaseInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + acquireCount*: uint32 + pAcquireSyncs*: ptr VkDeviceMemory + pAcquireKeys*: ptr uint64 + pAcquireTimeouts*: ptr uint32 + releaseCount*: uint32 + pReleaseSyncs*: ptr VkDeviceMemory + pReleaseKeys*: ptr uint64 + VkImportSemaphoreWin32HandleInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + flags*: VkSemaphoreImportFlags + handleType*: VkExternalSemaphoreHandleTypeFlagBits + handle*: HANDLE + name*: LPCWSTR + VkExportSemaphoreWin32HandleInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pAttributes*: ptr SECURITY_ATTRIBUTES + dwAccess*: DWORD + name*: LPCWSTR + VkD3D12FenceSubmitInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + waitSemaphoreValuesCount*: uint32 + pWaitSemaphoreValues*: ptr uint64 + signalSemaphoreValuesCount*: uint32 + pSignalSemaphoreValues*: ptr uint64 + VkSemaphoreGetWin32HandleInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + semaphore*: VkSemaphore + handleType*: VkExternalSemaphoreHandleTypeFlagBits + VkImportFenceWin32HandleInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + fence*: VkFence + flags*: VkFenceImportFlags + handleType*: VkExternalFenceHandleTypeFlagBits + handle*: HANDLE + name*: LPCWSTR + VkExportFenceWin32HandleInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + pAttributes*: ptr SECURITY_ATTRIBUTES + dwAccess*: DWORD + name*: LPCWSTR + VkFenceGetWin32HandleInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + fence*: VkFence + handleType*: VkExternalFenceHandleTypeFlagBits + VkSurfaceFullScreenExclusiveInfoEXT* = object + sType*: VkStructureType + pNext*: pointer + fullScreenExclusive*: VkFullScreenExclusiveEXT + VkSurfaceFullScreenExclusiveWin32InfoEXT* = object + sType*: VkStructureType + pNext*: pointer + hmonitor*: HMONITOR + VkSurfaceCapabilitiesFullScreenExclusiveEXT* = object + sType*: VkStructureType + pNext*: pointer + fullScreenExclusiveSupported*: VkBool32 + HINSTANCE *{.header: "windows.h".} = object + HWND *{.header: "windows.h".} = object + HMONITOR *{.header: "windows.h".} = object + HANDLE *{.header: "windows.h".} = object + SECURITY_ATTRIBUTES *{.header: "windows.h".} = object + DWORD *{.header: "windows.h".} = object + LPCWSTR *{.header: "windows.h".} = object +# extension VK_KHR_external_semaphore_win32 +var + vkImportSemaphoreWin32HandleKHR*: proc(device: VkDevice, pImportSemaphoreWin32HandleInfo: ptr VkImportSemaphoreWin32HandleInfoKHR): VkResult {.stdcall.} + vkGetSemaphoreWin32HandleKHR*: proc(device: VkDevice, pGetWin32HandleInfo: ptr VkSemaphoreGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.} +proc loadVK_KHR_external_semaphore_win32*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkImportSemaphoreWin32HandleKHR = cast[proc(device: VkDevice, pImportSemaphoreWin32HandleInfo: ptr VkImportSemaphoreWin32HandleInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkImportSemaphoreWin32HandleKHR")) + vkGetSemaphoreWin32HandleKHR = cast[proc(device: VkDevice, pGetWin32HandleInfo: ptr VkSemaphoreGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSemaphoreWin32HandleKHR")) + +# extension VK_KHR_external_memory_win32 +var + vkGetMemoryWin32HandleKHR*: proc(device: VkDevice, pGetWin32HandleInfo: ptr VkMemoryGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.} + vkGetMemoryWin32HandlePropertiesKHR*: proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, handle: HANDLE, pMemoryWin32HandleProperties: ptr VkMemoryWin32HandlePropertiesKHR): VkResult {.stdcall.} +proc loadVK_KHR_external_memory_win32*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkGetMemoryWin32HandleKHR = cast[proc(device: VkDevice, pGetWin32HandleInfo: ptr VkMemoryGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryWin32HandleKHR")) + vkGetMemoryWin32HandlePropertiesKHR = cast[proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, handle: HANDLE, pMemoryWin32HandleProperties: ptr VkMemoryWin32HandlePropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryWin32HandlePropertiesKHR")) + +# extension VK_KHR_external_fence_win32 +var + vkImportFenceWin32HandleKHR*: proc(device: VkDevice, pImportFenceWin32HandleInfo: ptr VkImportFenceWin32HandleInfoKHR): VkResult {.stdcall.} + vkGetFenceWin32HandleKHR*: proc(device: VkDevice, pGetWin32HandleInfo: ptr VkFenceGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.} +proc loadVK_KHR_external_fence_win32*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + vkImportFenceWin32HandleKHR = cast[proc(device: VkDevice, pImportFenceWin32HandleInfo: ptr VkImportFenceWin32HandleInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkImportFenceWin32HandleKHR")) + vkGetFenceWin32HandleKHR = cast[proc(device: VkDevice, pGetWin32HandleInfo: ptr VkFenceGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetFenceWin32HandleKHR")) + +proc loadVK_KHR_win32_keyed_mutex*(instance: VkInstance) = + loadVK_KHR_external_memory_win32(instance) + +# extension VK_NV_external_memory_win32 +var + vkGetMemoryWin32HandleNV*: proc(device: VkDevice, memory: VkDeviceMemory, handleType: VkExternalMemoryHandleTypeFlagsNV, pHandle: ptr HANDLE): VkResult {.stdcall.} +proc loadVK_NV_external_memory_win32*(instance: VkInstance) = + loadVK_NV_external_memory(instance) + vkGetMemoryWin32HandleNV = cast[proc(device: VkDevice, memory: VkDeviceMemory, handleType: VkExternalMemoryHandleTypeFlagsNV, pHandle: ptr HANDLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryWin32HandleNV")) + +# extension VK_EXT_full_screen_exclusive +var + vkGetPhysicalDeviceSurfacePresentModes2EXT*: proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pPresentModeCount: ptr uint32, pPresentModes: ptr VkPresentModeKHR): VkResult {.stdcall.} + vkAcquireFullScreenExclusiveModeEXT*: proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.} + vkReleaseFullScreenExclusiveModeEXT*: proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.} + vkGetDeviceGroupSurfacePresentModes2EXT*: proc(device: VkDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pModes: ptr VkDeviceGroupPresentModeFlagsKHR): VkResult {.stdcall.} +proc loadVK_EXT_full_screen_exclusive*(instance: VkInstance) = + loadVK_VERSION_1_1(instance) + loadVK_KHR_surface(instance) + loadVK_KHR_get_surface_capabilities2(instance) + loadVK_KHR_swapchain(instance) + vkGetPhysicalDeviceSurfacePresentModes2EXT = cast[proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pPresentModeCount: ptr uint32, pPresentModes: ptr VkPresentModeKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModes2EXT")) + vkAcquireFullScreenExclusiveModeEXT = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireFullScreenExclusiveModeEXT")) + vkReleaseFullScreenExclusiveModeEXT = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkReleaseFullScreenExclusiveModeEXT")) + vkGetDeviceGroupSurfacePresentModes2EXT = cast[proc(device: VkDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pModes: ptr VkDeviceGroupPresentModeFlagsKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceGroupSurfacePresentModes2EXT")) + vkGetDeviceGroupSurfacePresentModes2EXT = cast[proc(device: VkDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pModes: ptr VkDeviceGroupPresentModeFlagsKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceGroupSurfacePresentModes2EXT")) + +# extension VK_KHR_win32_surface +var + vkCreateWin32SurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkWin32SurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceWin32PresentationSupportKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32): VkBool32 {.stdcall.} +proc loadVK_KHR_win32_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateWin32SurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkWin32SurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR")) + vkGetPhysicalDeviceWin32PresentationSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR")) + +# extension VK_NV_acquire_winrt_display +var + vkAcquireWinrtDisplayNV*: proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR): VkResult {.stdcall.} + vkGetWinrtDisplayNV*: proc(physicalDevice: VkPhysicalDevice, deviceRelativeId: uint32, pDisplay: ptr VkDisplayKHR): VkResult {.stdcall.} +proc loadVK_NV_acquire_winrt_display*(instance: VkInstance) = + loadVK_EXT_direct_mode_display(instance) + vkAcquireWinrtDisplayNV = cast[proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireWinrtDisplayNV")) + vkGetWinrtDisplayNV = cast[proc(physicalDevice: VkPhysicalDevice, deviceRelativeId: uint32, pDisplay: ptr VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetWinrtDisplayNV")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/xcb.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/xcb.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,18 @@ +type + VkXcbSurfaceCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkXcbSurfaceCreateFlagsKHR + connection*: ptr xcb_connection_t + window*: xcb_window_t + xcb_connection_t *{.header: "xcb/xcb.h".} = object + xcb_visualid_t *{.header: "xcb/xcb.h".} = object + xcb_window_t *{.header: "xcb/xcb.h".} = object +# extension VK_KHR_xcb_surface +var + vkCreateXcbSurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkXcbSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceXcbPresentationSupportKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, connection: ptr xcb_connection_t, visual_id: xcb_visualid_t): VkBool32 {.stdcall.} +proc loadVK_KHR_xcb_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateXcbSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkXcbSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR")) + vkGetPhysicalDeviceXcbPresentationSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, connection: ptr xcb_connection_t, visual_id: xcb_visualid_t): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/xlib.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/xlib.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,18 @@ +type + VkXlibSurfaceCreateInfoKHR* = object + sType*: VkStructureType + pNext*: pointer + flags*: VkXlibSurfaceCreateFlagsKHR + dpy*: ptr Display + window*: Window + Display *{.header: "X11/Xlib.h".} = object + VisualID *{.header: "X11/Xlib.h".} = object + Window *{.header: "X11/Xlib.h".} = object +# extension VK_KHR_xlib_surface +var + vkCreateXlibSurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkXlibSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} + vkGetPhysicalDeviceXlibPresentationSupportKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, dpy: ptr Display, visualID: VisualID): VkBool32 {.stdcall.} +proc loadVK_KHR_xlib_surface*(instance: VkInstance) = + loadVK_KHR_surface(instance) + vkCreateXlibSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkXlibSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR")) + vkGetPhysicalDeviceXlibPresentationSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, dpy: ptr Display, visualID: VisualID): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/platform/xlib_xrandr.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/platform/xlib_xrandr.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,13 @@ +type + Display *{.header: "X11/Xlib.h".} = object + VisualID *{.header: "X11/Xlib.h".} = object + Window *{.header: "X11/Xlib.h".} = object + RROutput *{.header: "X11/extensions/Xrandr.h".} = object +# extension VK_EXT_acquire_xlib_display +var + vkAcquireXlibDisplayEXT*: proc(physicalDevice: VkPhysicalDevice, dpy: ptr Display, display: VkDisplayKHR): VkResult {.stdcall.} + vkGetRandROutputDisplayEXT*: proc(physicalDevice: VkPhysicalDevice, dpy: ptr Display, rrOutput: RROutput, pDisplay: ptr VkDisplayKHR): VkResult {.stdcall.} +proc loadVK_EXT_acquire_xlib_display*(instance: VkInstance) = + loadVK_EXT_direct_mode_display(instance) + vkAcquireXlibDisplayEXT = cast[proc(physicalDevice: VkPhysicalDevice, dpy: ptr Display, display: VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireXlibDisplayEXT")) + vkGetRandROutputDisplayEXT = cast[proc(physicalDevice: VkPhysicalDevice, dpy: ptr Display, rrOutput: RROutput, pDisplay: ptr VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRandROutputDisplayEXT")) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/renderpass.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/renderpass.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,166 @@ +import std/options + +import ../core +import ../material +import ./device +import ./physicaldevice +import ./pipeline +import ./shader +import ./framebuffer + +type + Subpass* = object + clearColor*: Vec4f + pipelineBindPoint*: VkPipelineBindPoint + flags: VkSubpassDescriptionFlags + outputs: seq[VkAttachmentReference] + depthStencil: Option[VkAttachmentReference] + shaderPipelines*: seq[(MaterialType, ShaderPipeline)] + RenderPass* = object + vk*: VkRenderPass + device*: Device + subpasses*: seq[Subpass] + +proc createRenderPass*( + device: Device, + attachments: seq[VkAttachmentDescription], + subpasses: seq[Subpass], + dependencies: seq[VkSubpassDependency], +): RenderPass = + assert device.vk.valid + var pAttachments = attachments + var pSubpasses = subpasses + var pDependencies = dependencies + + var subpassesList: seq[VkSubpassDescription] + for subpass in pSubpasses.mitems: + subpassesList.add VkSubpassDescription( + flags: subpass.flags, + pipelineBindPoint: subpass.pipelineBindPoint, + inputAttachmentCount: 0, + pInputAttachments: nil, + colorAttachmentCount: uint32(subpass.outputs.len), + pColorAttachments: subpass.outputs.toCPointer, + pResolveAttachments: nil, + pDepthStencilAttachment: if subpass.depthStencil.isSome: addr(subpass.depthStencil.get) else: nil, + preserveAttachmentCount: 0, + pPreserveAttachments: nil, + ) + + var createInfo = VkRenderPassCreateInfo( + sType: VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + attachmentCount: uint32(pAttachments.len), + pAttachments: pAttachments.toCPointer, + subpassCount: uint32(subpassesList.len), + pSubpasses: subpassesList.toCPointer, + dependencyCount: uint32(pDependencies.len), + pDependencies: pDependencies.toCPointer, + ) + result.device = device + result.subpasses = pSubpasses + checkVkResult device.vk.vkCreateRenderPass(addr(createInfo), nil, addr(result.vk)) + +proc simpleForwardRenderPass*( + device: Device, + shaders: openArray[(MaterialType, ShaderConfiguration)], + inFlightFrames=2, + clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32]), + backFaceCulling=true, +): RenderPass = + # TODO: check wether materials are compatible with the assigned shaders + {.warning: "Need to implement material -> shader compatability" .} + + assert device.vk.valid + for (_, shaderconfig) in shaders: + assert shaderconfig.outputs.len == 1 + var + attachments = @[VkAttachmentDescription( + format: device.physicalDevice.getSurfaceFormats().filterSurfaceFormat().format, + samples: VK_SAMPLE_COUNT_1_BIT, + loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, + storeOp: VK_ATTACHMENT_STORE_OP_STORE, + stencilLoadOp: VK_ATTACHMENT_LOAD_OP_DONT_CARE, + stencilStoreOp: VK_ATTACHMENT_STORE_OP_DONT_CARE, + initialLayout: VK_IMAGE_LAYOUT_UNDEFINED, + finalLayout: VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + )] + subpasses = @[ + Subpass( + pipelineBindPoint: VK_PIPELINE_BIND_POINT_GRAPHICS, + outputs: @[VkAttachmentReference(attachment: 0, layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)], + clearColor: clearColor + ) + ] + # dependencies seems to be optional, TODO: benchmark difference + dependencies = @[VkSubpassDependency( + srcSubpass: VK_SUBPASS_EXTERNAL, + dstSubpass: 0, + srcStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT], + srcAccessMask: VkAccessFlags(0), + dstStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT], + dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT], + )] + result = device.createRenderPass(attachments=attachments, subpasses=subpasses, dependencies=dependencies) + for (materialtype, shaderconfig) in shaders: + result.subpasses[0].shaderPipelines.add (materialtype, device.createPipeline(result.vk, shaderconfig, inFlightFrames, 0, backFaceCulling=backFaceCulling)) + + +proc beginRenderCommands*(commandBuffer: VkCommandBuffer, renderpass: RenderPass, framebuffer: Framebuffer) = + assert commandBuffer.valid + assert renderpass.vk.valid + assert framebuffer.vk.valid + let + w = framebuffer.dimension.x + h = framebuffer.dimension.y + + var clearColors: seq[VkClearValue] + for subpass in renderpass.subpasses: + clearColors.add(VkClearValue(color: VkClearColorValue(float32: subpass.clearColor))) + var + beginInfo = VkCommandBufferBeginInfo( + sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + pInheritanceInfo: nil, + ) + renderPassInfo = VkRenderPassBeginInfo( + sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + renderPass: renderPass.vk, + framebuffer: framebuffer.vk, + renderArea: VkRect2D( + offset: VkOffset2D(x: 0, y: 0), + extent: VkExtent2D(width: w, height: h), + ), + clearValueCount: uint32(clearColors.len), + pClearValues: clearColors.toCPointer(), + ) + viewport = VkViewport( + x: 0.0, + y: 0.0, + width: (float)w, + height: (float)h, + minDepth: 0.0, + maxDepth: 1.0, + ) + scissor = VkRect2D( + offset: VkOffset2D(x: 0, y: 0), + extent: VkExtent2D(width: w, height: h) + ) + checkVkResult commandBuffer.vkResetCommandBuffer(VkCommandBufferResetFlags(0)) + checkVkResult commandBuffer.vkBeginCommandBuffer(addr(beginInfo)) + commandBuffer.vkCmdBeginRenderPass(addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE) + commandBuffer.vkCmdSetViewport(firstViewport=0, viewportCount=1, addr(viewport)) + commandBuffer.vkCmdSetScissor(firstScissor=0, scissorCount=1, addr(scissor)) + +proc endRenderCommands*(commandBuffer: VkCommandBuffer) = + commandBuffer.vkCmdEndRenderPass() + checkVkResult commandBuffer.vkEndCommandBuffer() + + +proc destroy*(renderPass: var RenderPass) = + assert renderPass.device.vk.valid + assert renderPass.vk.valid + renderPass.device.vk.vkDestroyRenderPass(renderPass.vk, nil) + renderPass.vk.reset + for i in 0 ..< renderPass.subpasses.len: + for _, pipeline in renderPass.subpasses[i].shaderPipelines.mitems: + pipeline.destroy() + renderPass.subpasses = @[] diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/shader.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/shader.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,218 @@ +import std/typetraits +import std/os +import std/enumerate +import std/logging +import std/hashes +import std/strformat +import std/strutils +import std/compilesettings + +import ../core +import ./device + +const DEFAULT_SHADER_VERSION = 450 +const DEFAULT_SHADER_ENTRYPOINT = "main" + +let logger = newConsoleLogger() +addHandler(logger) + +type + ShaderModule* = object + device: Device + vk*: VkShaderModule + stage*: VkShaderStageFlagBits + configuration*: ShaderConfiguration + ShaderConfiguration* = object + vertexBinary: seq[uint32] + fragmentBinary: seq[uint32] + entrypoint: string + inputs*: seq[ShaderAttribute] + intermediates*: seq[ShaderAttribute] + outputs*: seq[ShaderAttribute] + uniforms*: seq[ShaderAttribute] + samplers*: seq[ShaderAttribute] + + +proc compileGlslToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string, entrypoint: string): seq[uint32] {.compileTime.} = + func stage2string(stage: VkShaderStageFlagBits): string {.compileTime.} = + case stage + of VK_SHADER_STAGE_VERTEX_BIT: "vert" + of VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: "tesc" + of VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: "tese" + of VK_SHADER_STAGE_GEOMETRY_BIT: "geom" + of VK_SHADER_STAGE_FRAGMENT_BIT: "frag" + of VK_SHADER_STAGE_COMPUTE_BIT: "comp" + else: "" + + when defined(nimcheck): # will not run if nimcheck is running + return result + + let + stagename = stage2string(stage) + shaderHash = hash(shaderSource) + # cross compilation for windows workaround, sorry computer + shaderfile = getTempDir() / &"shader_{shaderHash}.{stagename}" + projectPath = querySetting(projectPath) + + echo "shader of type ", stage, ", entrypoint ", entrypoint + for i, line in enumerate(shaderSource.splitlines()): + echo " ", i + 1, " ", line + var glslExe = "glslangValidator" + when defined(windows): + glslExe = glslExe & "." & ExeExt + let command = &"{projectPath.joinPath(glslExe)} --entry-point {entrypoint} -V --stdin -S {stagename} -o {shaderfile}" + echo "run: ", command + discard staticExecChecked( + command = command, + input = shaderSource + ) + + when defined(mingw) and defined(linux): # required for crosscompilation, path separators get messed up + let shaderbinary = staticRead shaderfile.replace("\\", "/") + else: + let shaderbinary = staticRead shaderfile + + var i = 0 + while i < shaderbinary.len: + result.add( + (uint32(shaderbinary[i + 0]) shl 0) or + (uint32(shaderbinary[i + 1]) shl 8) or + (uint32(shaderbinary[i + 2]) shl 16) or + (uint32(shaderbinary[i + 3]) shl 24) + ) + i += 4 + +proc compileGlslCode*( + stage: VkShaderStageFlagBits, + inputs: openArray[ShaderAttribute]=[], + uniforms: openArray[ShaderAttribute]=[], + samplers: openArray[ShaderAttribute]=[], + outputs: openArray[ShaderAttribute]=[], + version=DEFAULT_SHADER_VERSION , + entrypoint=DEFAULT_SHADER_ENTRYPOINT , + main: string +): seq[uint32] {.compileTime.} = + + let code = @[&"#version {version}", "#extension GL_EXT_scalar_block_layout : require", ""] & + (if inputs.len > 0: inputs.glslInput() & @[""] else: @[]) & + (if uniforms.len > 0: uniforms.glslUniforms(binding=0) & @[""] else: @[]) & + (if samplers.len > 0: samplers.glslSamplers(basebinding=if uniforms.len > 0: 1 else: 0) & @[""] else: @[]) & + (if outputs.len > 0: outputs.glslOutput() & @[""] else: @[]) & + @[&"void {entrypoint}(){{"] & + main & + @[&"}}"] + compileGlslToSPIRV(stage, code.join("\n"), entrypoint) + +proc createShaderConfiguration*( + inputs: openArray[ShaderAttribute]=[], + intermediates: openArray[ShaderAttribute]=[], + outputs: openArray[ShaderAttribute]=[], + uniforms: openArray[ShaderAttribute]=[], + samplers: openArray[ShaderAttribute]=[], + version=DEFAULT_SHADER_VERSION , + entrypoint=DEFAULT_SHADER_ENTRYPOINT , + vertexCode: string, + fragmentCode: string, +): ShaderConfiguration {.compileTime.} = + ShaderConfiguration( + vertexBinary: compileGlslCode( + stage=VK_SHADER_STAGE_VERTEX_BIT, + inputs=inputs, + outputs=intermediates, + uniforms=uniforms, + samplers=samplers, + main=vertexCode, + ), + fragmentBinary: compileGlslCode( + stage=VK_SHADER_STAGE_FRAGMENT_BIT, + inputs=intermediates, + outputs=outputs, + uniforms=uniforms, + samplers=samplers, + main=fragmentCode, + ), + entrypoint: entrypoint, + inputs: @inputs, + intermediates: @intermediates, + outputs: @outputs, + uniforms: @uniforms, + samplers: @samplers, + ) + + +proc createShaderModules*( + device: Device, + shaderConfiguration: ShaderConfiguration, +): (ShaderModule, ShaderModule) = + assert device.vk.valid + assert len(shaderConfiguration.vertexBinary) > 0 + assert len(shaderConfiguration.fragmentBinary) > 0 + + result[0].device = device + result[1].device = device + result[0].configuration = shaderConfiguration + result[1].configuration = shaderConfiguration + result[0].stage = VK_SHADER_STAGE_VERTEX_BIT + result[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT + + var createInfoVertex = VkShaderModuleCreateInfo( + sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + codeSize: uint(shaderConfiguration.vertexBinary.len * sizeof(uint32)), + pCode: addr(shaderConfiguration.vertexBinary[0]), + ) + checkVkResult vkCreateShaderModule(device.vk, addr(createInfoVertex), nil, addr(result[0].vk)) + var createInfoFragment = VkShaderModuleCreateInfo( + sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + codeSize: uint(shaderConfiguration.fragmentBinary.len * sizeof(uint32)), + pCode: addr(shaderConfiguration.fragmentBinary[0]), + ) + checkVkResult vkCreateShaderModule(device.vk, addr(createInfoFragment), nil, addr(result[1].vk)) + +proc getVertexInputInfo*( + shaderConfiguration: ShaderConfiguration, + bindings: var seq[VkVertexInputBindingDescription], + attributes: var seq[VkVertexInputAttributeDescription], + baseBinding=0'u32 +): VkPipelineVertexInputStateCreateInfo = + var location = 0'u32 + var binding = baseBinding + + for attribute in shaderConfiguration.inputs: + bindings.add VkVertexInputBindingDescription( + binding: binding, + stride: uint32(attribute.size), + inputRate: if attribute.perInstance: VK_VERTEX_INPUT_RATE_INSTANCE else: VK_VERTEX_INPUT_RATE_VERTEX, + ) + # allows to submit larger data structures like Mat44, for most other types will be 1 + for i in 0 ..< attribute.thetype.numberOfVertexInputAttributeDescriptors: + attributes.add VkVertexInputAttributeDescription( + binding: binding, + location: location, + format: attribute.thetype.getVkFormat, + offset: uint32(i * attribute.size(perDescriptor=true)), + ) + location += uint32(attribute.thetype.nLocationSlots) + inc binding + + return VkPipelineVertexInputStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + vertexBindingDescriptionCount: uint32(bindings.len), + pVertexBindingDescriptions: bindings.toCPointer, + vertexAttributeDescriptionCount: uint32(attributes.len), + pVertexAttributeDescriptions: attributes.toCPointer, + ) + + +proc getPipelineInfo*(shader: ShaderModule): VkPipelineShaderStageCreateInfo = + VkPipelineShaderStageCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + stage: shader.stage, + module: shader.vk, + pName: cstring(shader.configuration.entrypoint), + ) + +proc destroy*(shader: var ShaderModule) = + assert shader.device.vk.valid + assert shader.vk.valid + shader.device.vk.vkDestroyShaderModule(shader.vk, nil) + shader.vk.reset diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/swapchain.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/swapchain.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,231 @@ +import std/options +import std/strformat +import std/logging + +import ../core +import ./device +import ./physicaldevice +import ./image +import ./framebuffer +import ./commandbuffer +import ./syncing + +type + Swapchain* = object + device*: Device + vk*: VkSwapchainKHR + dimension*: TVec2[uint32] + nImages*: uint32 + imageviews*: seq[ImageView] + framebuffers*: seq[Framebuffer] + currentInFlight*: int + currentFramebufferIndex: uint32 + framesRendered*: uint64 + queueFinishedFence*: seq[Fence] + imageAvailableSemaphore*: seq[Semaphore] + renderFinishedSemaphore*: seq[Semaphore] + commandBufferPool: CommandBufferPool + # required for recreation: + renderPass: VkRenderPass + surfaceFormat: VkSurfaceFormatKHR + queueFamily: QueueFamily + imageCount: uint32 + presentMode: VkPresentModeKHR + inFlightFrames*: int + + +proc createSwapchain*( + device: Device, + renderPass: VkRenderPass, + surfaceFormat: VkSurfaceFormatKHR, + queueFamily: QueueFamily, + desiredNumberOfImages=3'u32, + preferedPresentMode: VkPresentModeKHR=VK_PRESENT_MODE_MAILBOX_KHR, + inFlightFrames=2, + oldSwapchain=VkSwapchainKHR(0) +): Option[Swapchain] = + assert device.vk.valid + assert device.physicalDevice.vk.valid + assert renderPass.valid + assert inFlightFrames > 0 + + var capabilities = device.physicalDevice.getSurfaceCapabilities() + if capabilities.currentExtent.width == 0 or capabilities.currentExtent.height == 0: + return none(Swapchain) + + var imageCount = desiredNumberOfImages + + const PRESENTMODES_BY_PREFERENCE = [ + VK_PRESENT_MODE_MAILBOX_KHR, + VK_PRESENT_MODE_FIFO_RELAXED_KHR, + VK_PRESENT_MODE_FIFO_KHR, + VK_PRESENT_MODE_IMMEDIATE_KHR, + VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR, + VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, + ] + var supportedModes = device.physicalDevice.getSurfacePresentModes() + var presentMode: VkPresentModeKHR + for mode in PRESENTMODES_BY_PREFERENCE: + if mode in supportedModes: + presentMode = mode + break + + # following is according to vulkan specs + if presentMode in [VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR]: + imageCount = 1 + else: + imageCount = max(imageCount, capabilities.minImageCount) + if capabilities.maxImageCount != 0: + imageCount = min(imageCount, capabilities.maxImageCount) + var createInfo = VkSwapchainCreateInfoKHR( + sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + surface: device.physicalDevice.surface, + minImageCount: imageCount, + imageFormat: surfaceFormat.format, + imageColorSpace: surfaceFormat.colorSpace, + imageExtent: capabilities.currentExtent, + imageArrayLayers: 1, + imageUsage: toBits [VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT], + # VK_SHARING_MODE_CONCURRENT no supported currently + imageSharingMode: VK_SHARING_MODE_EXCLUSIVE, + preTransform: capabilities.currentTransform, + compositeAlpha: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, # only used for blending with other windows, can be opaque + presentMode: presentMode, + clipped: true, + oldSwapchain: oldSwapchain, + ) + var + swapchain = Swapchain( + device: device, + surfaceFormat: surfaceFormat, + dimension: TVec2[uint32]([capabilities.currentExtent.width, capabilities.currentExtent.height]), + inFlightFrames: inFlightFrames, + queueFamily: queueFamily, + renderPass: renderPass + ) + + if device.vk.vkCreateSwapchainKHR(addr(createInfo), nil, addr(swapchain.vk)) == VK_SUCCESS: + var nImages: uint32 + checkVkResult device.vk.vkGetSwapchainImagesKHR(swapChain.vk, addr(nImages), nil) + swapchain.nImages = nImages + var images = newSeq[VkImage](nImages) + checkVkResult device.vk.vkGetSwapchainImagesKHR(swapChain.vk, addr(nImages), images.toCPointer) + for vkimage in images: + let image = VulkanImage(vk: vkimage, format: surfaceFormat.format, device: device) + let imageview = image.createImageView() + swapChain.imageviews.add imageview + swapChain.framebuffers.add swapchain.device.createFramebuffer(renderPass, [imageview], swapchain.dimension) + for i in 0 ..< swapchain.inFlightFrames: + swapchain.queueFinishedFence.add device.createFence() + swapchain.imageAvailableSemaphore.add device.createSemaphore() + swapchain.renderFinishedSemaphore.add device.createSemaphore() + swapchain.commandBufferPool = device.createCommandBufferPool(queueFamily, swapchain.inFlightFrames) + debug &"Created swapchain with: {nImages} framebuffers, {inFlightFrames} in-flight frames, {swapchain.dimension.x}x{swapchain.dimension.y}" + result = some(swapchain) + else: + result = none(Swapchain) + +proc currentFramebuffer*(swapchain: Swapchain): Framebuffer = + assert swapchain.device.vk.valid + assert swapchain.vk.valid + swapchain.framebuffers[swapchain.currentFramebufferIndex] + +proc nextFrame*(swapchain: var Swapchain): Option[VkCommandBuffer] = + assert swapchain.device.vk.valid + assert swapchain.vk.valid + + swapchain.currentInFlight = (swapchain.currentInFlight + 1) mod swapchain.inFlightFrames + swapchain.queueFinishedFence[swapchain.currentInFlight].wait() + + let nextImageResult = swapchain.device.vk.vkAcquireNextImageKHR( + swapchain.vk, + high(uint64), + swapchain.imageAvailableSemaphore[swapchain.currentInFlight].vk, + VkFence(0), + addr(swapchain.currentFramebufferIndex) + ) + + if nextImageResult == VK_SUCCESS: + swapchain.queueFinishedFence[swapchain.currentInFlight].reset() + result = some(swapchain.commandBufferPool.buffers[swapchain.currentInFlight]) + else: + result = none(VkCommandBuffer) + +proc swap*(swapchain: var Swapchain): bool = + assert swapchain.device.vk.valid + assert swapchain.vk.valid + assert swapchain.device.firstGraphicsQueue().isSome + assert swapchain.device.firstPresentationQueue().isSome + + var + commandBuffer = swapchain.commandBufferPool.buffers[swapchain.currentInFlight] + waitSemaphores = [swapchain.imageAvailableSemaphore[swapchain.currentInFlight].vk] + waitStages = [VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)] + submitInfo = VkSubmitInfo( + sType: VK_STRUCTURE_TYPE_SUBMIT_INFO, + waitSemaphoreCount: 1, + pWaitSemaphores: addr(waitSemaphores[0]), + pWaitDstStageMask: addr(waitStages[0]), + commandBufferCount: 1, + pCommandBuffers: addr(commandBuffer), + signalSemaphoreCount: 1, + pSignalSemaphores: addr(swapchain.renderFinishedSemaphore[swapchain.currentInFlight].vk), + ) + checkVkResult vkQueueSubmit( + swapchain.device.firstGraphicsQueue().get.vk, + 1, + addr(submitInfo), + swapchain.queueFinishedFence[swapchain.currentInFlight].vk + ) + + var presentInfo = VkPresentInfoKHR( + sType: VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + waitSemaphoreCount: 1, + pWaitSemaphores: addr(swapchain.renderFinishedSemaphore[swapchain.currentInFlight].vk), + swapchainCount: 1, + pSwapchains: addr(swapchain.vk), + pImageIndices: addr(swapchain.currentFramebufferIndex), + pResults: nil, + ) + let presentResult = vkQueuePresentKHR(swapchain.device.firstPresentationQueue().get().vk, addr(presentInfo)) + if presentResult != VK_SUCCESS: + return false + + inc swapchain.framesRendered + return true + + +proc destroy*(swapchain: var Swapchain) = + assert swapchain.vk.valid + assert swapchain.commandBufferPool.vk.valid + + for imageview in swapchain.imageviews.mitems: + assert imageview.vk.valid + imageview.destroy() + for framebuffer in swapchain.framebuffers.mitems: + assert framebuffer.vk.valid + framebuffer.destroy() + swapchain.commandBufferPool.destroy() + for i in 0 ..< swapchain.inFlightFrames: + assert swapchain.queueFinishedFence[i].vk.valid + assert swapchain.imageAvailableSemaphore[i].vk.valid + assert swapchain.renderFinishedSemaphore[i].vk.valid + swapchain.queueFinishedFence[i].destroy() + swapchain.imageAvailableSemaphore[i].destroy() + swapchain.renderFinishedSemaphore[i].destroy() + + swapchain.device.vk.vkDestroySwapchainKHR(swapchain.vk, nil) + swapchain.vk.reset() + +proc recreate*(swapchain: var Swapchain): Option[Swapchain] = + assert swapchain.vk.valid + assert swapchain.device.vk.valid + result = createSwapchain( + device=swapchain.device, + renderPass=swapchain.renderPass, + surfaceFormat=swapchain.surfaceFormat, + queueFamily=swapchain.queueFamily, + desiredNumberOfImages=swapchain.imageCount, + inFlightFrames=swapchain.inFlightFrames, + oldSwapchain=swapchain.vk, + ) diff -r 611f9cee7495 -r 1c3e74f24db0 semicongine/vulkan/syncing.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/syncing.nim Sat Dec 02 22:26:26 2023 +0700 @@ -0,0 +1,49 @@ +import ../core +import ./device + +type + Semaphore* = object + vk*: VkSemaphore + device: Device + Fence* = object + vk*: VkFence + device: Device + +proc createSemaphore*(device: Device): Semaphore = + assert device.vk.valid + var semaphoreInfo = VkSemaphoreCreateInfo(sType: VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO) + result.device = device + checkVkResult device.vk.vkCreateSemaphore(addr(semaphoreInfo), nil, addr(result.vk)) + +proc createFence*(device: Device): Fence = + assert device.vk.valid + var fenceInfo = VkFenceCreateInfo( + sType: VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + flags: toBits [VK_FENCE_CREATE_SIGNALED_BIT] + ) + result.device = device + checkVkResult device.vk.vkCreateFence(addr(fenceInfo), nil, addr(result.vk)) + +proc wait*(fence: Fence) = + assert fence.device.vk.valid + assert fence.vk.valid + var varFence = fence.vk + checkVkResult vkWaitForFences(fence.device.vk, 1, addr(varFence), false, high(uint64)) + +proc reset*(fence: Fence) = + assert fence.device.vk.valid + assert fence.vk.valid + var varFence = fence.vk + checkVkResult vkResetFences(fence.device.vk, 1, addr(varFence)) + +proc destroy*(semaphore: var Semaphore) = + assert semaphore.device.vk.valid + assert semaphore.vk.valid + semaphore.device.vk.vkDestroySemaphore(semaphore.vk, nil) + semaphore.vk.reset + +proc destroy*(fence: var Fence) = + assert fence.device.vk.valid + assert fence.vk.valid + fence.device.vk.vkDestroyFence(fence.vk, nil) + fence.vk.reset diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine.nim --- a/src/semicongine.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -import std/tables -export tables # necessary to use some features without weird compilation error - -import semicongine/core -export core - -import semicongine/audio -import semicongine/animation -import semicongine/engine -import semicongine/collision -import semicongine/scene -import semicongine/events -import semicongine/material -import semicongine/mesh -import semicongine/noise -import semicongine/renderer -import semicongine/resources -import semicongine/settings -import semicongine/text -import semicongine/platform/window -import semicongine/vulkan - -export audio -export animation -export engine -export collision -export scene -export events -export material -export mesh -export noise -export renderer -export resources -export settings -export text -export window -export vulkan diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/animation.nim --- a/src/semicongine/animation.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -import std/sugar -import std/tables -import std/math -import std/sequtils -import std/algorithm - -import ./core/matrix - -type - Ease* = enum - None - Linear - Pow2 - Pow3 - Pow4 - Pow5 - Expo - Sine - Circ - AnimationTime* = 0'f32 .. 1'f32 - Direction* = enum - Forward - Backward - Alternate - Keyframe[T] = object - timestamp: AnimationTime - value : T - easeIn: Ease - easeOut: Ease - Animation*[T] = object - animationFunction: (t: AnimationTime) -> T - duration: float32 - direction: Direction - iterations: int - AnimationPlayer*[T] = object - animation*: Animation[T] - currentTime*: float32 - playing*: bool - currentDirection: int - currentIteration: int - currentValue*: T - -func easeConst(x: float32): float32 = 0 -func easeLinear(x: float32): float32 = x -func easePow2(x: float32): float32 = x * x -func easePow3(x: float32): float32 = x * x * x -func easePow4(x: float32): float32 = x * x * x * x -func easePow5(x: float32): float32 = x * x * x * x * x -func easeExpo(x: float32): float32 = ( if x == 0: 0'f32 else: pow(2'f32, 10'f32 * x - 10'f32) ) -func easeSine(x: float32): float32 = 1'f32 - cos((x * PI) / 2'f32) -func easeCirc(x: float32): float32 = 1'f32 - sqrt(1'f32 - pow(x, 2'f32)) - -const EASEFUNC_MAP = { - None: easeConst, - Linear: easeLinear, - Pow2: easePow2, - Pow3: easePow3, - Pow4: easePow4, - Pow5: easePow5, - Expo: easeExpo, - Sine: easeSine, - Circ: easeCirc, -}.toTable() - -func makeEaseOut(f: proc(x: float32): float32 {.noSideEffect.}): auto = - func wrapper(x: float32): float32 = - 1 - f(1 - x) - return wrapper - -func combine(f1: proc(x: float32): float32 {.noSideEffect.}, f2: proc(x: float32): float32 {.noSideEffect.}): auto = - func wrapper(x: float32): float32 = - if x < 0.5: f1(x * 2) * 0.5 - else: f2((x - 0.5) * 2) * 0.5 + 0.5 - return wrapper - -func interpol(keyframe: Keyframe, t: float32): float32 = - if keyframe.easeOut == None: - return EASEFUNC_MAP[keyframe.easeIn](t) - elif keyframe.easeIn == None: - return EASEFUNC_MAP[keyframe.easeOut](t) - else: - return combine(EASEFUNC_MAP[keyframe.easeIn], makeEaseOut(EASEFUNC_MAP[keyframe.easeOut]))(t) - -func keyframe*[T](timestamp: AnimationTime, value: T, easeIn=Linear, easeOut=None): Keyframe[T] = - Keyframe[T](timestamp: timestamp, value: value, easeIn: easeIn, easeOut: easeOut) - -func newAnimation*[T](keyframes: openArray[Keyframe[T]], duration: float32, direction=Forward, iterations=1): Animation[T] = - assert keyframes.len >= 2, "An animation needs at least 2 keyframes" - assert keyframes[0].timestamp == 0, "An animation's first keyframe needs to have timestamp=0" - assert keyframes[^1].timestamp == 1, "An animation's last keyframe needs to have timestamp=1" - var last = keyframes[0].timestamp - for kf in keyframes[1 .. ^1]: - assert kf.timestamp > last, "Succeding keyframes must have increasing timestamps" - last = kf.timestamp - - let theKeyframes = keyframes.toSeq - - proc animationFunc(t: AnimationTime): T = - var i = 0 - while i < theKeyframes.len - 1: - if theKeyframes[i].timestamp > t: - break - inc i - - let - keyFrameDist = theKeyframes[i].timestamp - theKeyframes[i - 1].timestamp - timestampDist = t - theKeyframes[i - 1].timestamp - x = timestampDist / keyFrameDist - - let value = theKeyframes[i - 1].interpol(x) - return theKeyframes[i].value * value + theKeyframes[i - 1].value * (1 - value) - - Animation[T]( - animationFunction: animationFunc, - duration: duration, - direction: direction, - iterations: iterations - ) - -func newAnimation*[T](fun: (t: AnimationTime) -> T, duration: float32, direction=Forward, iterations=1): Animation[T] = - Animation[T]( - animationFunction: fun, - duration: duration, - direction: direction, - iterations: iterations - ) - -proc reset*(player: var AnimationPlayer) = - player.currentValue = player.animation.animationFunction(0) - player.currentTime = 0 - player.currentDirection = if player.animation.direction == Backward: -1 else : 1 - player.currentIteration = player.animation.iterations - - -proc newAnimationPlayer*[T](animation: Animation[T]): AnimationPlayer[T] = - result = AnimationPlayer[T](animation: animation, playing: false) - result.reset() - -proc newAnimationPlayer*[T](value: T = default(T)): AnimationPlayer[T] = - newAnimationPlayer[T](newAnimation[T]((t: AnimationTime) => value, 0)) - -func start*(player: var AnimationPlayer) = - player.playing = true - -func stop*(player: var AnimationPlayer) = - player.playing = false - -proc advance*[T](player: var AnimationPlayer[T], dt: float32): T = - # TODO: check this function, not 100% correct I think - if player.playing: - player.currentTime += float32(player.currentDirection) * dt - if not (0 <= player.currentTime and player.currentTime < player.animation.duration): - dec player.currentIteration - # last iteration reached - if player.currentIteration <= 0 and player.animation.iterations != 0: - player.stop() - # more iterations - else: - case player.animation.direction: - of Forward: - player.currentTime = player.currentTime - player.animation.duration - of Backward: - player.currentTime = player.currentTime + player.animation.duration - of Alternate: - player.currentDirection = -player.currentDirection - player.currentTime += float32(player.currentDirection) * dt * 2'f32 - - player.currentValue = player.animation.animationFunction( - max(low(AnimationTime), min(player.currentTime / player.animation.duration, high(AnimationTime))) - ) - return player.currentValue diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/audio.nim --- a/src/semicongine/audio.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,211 +0,0 @@ -import std/tables -import std/locks -import std/logging except Level - -when defined(windows): # used for setting audio thread priority - import winim -when defined(linux): - import std/posix - -import ./core -import ./platform/audio -import ./resources - -export audiotypes - -const NBUFFERS = 4 -const BUFFERSAMPLECOUNT = 2048 - -type - Playback = object - sound: Sound - position: int - loop: bool - levelLeft: Level - levelRight: Level - Track = object - playing: Table[uint64, Playback] - level: Level - Mixer* = object - playbackCounter: uint64 - tracks: Table[string, Track] - sounds*: Table[string, Sound] - level: Level - device: NativeSoundDevice - lock: Lock - buffers: seq[SoundData] - currentBuffer: int - -proc initMixer*(): Mixer = - result = Mixer( - tracks: {"": Track(level: 1'f)}.toTable, - level: 1'f, - ) - result.lock.initLock() - -proc setupDevice(mixer: var Mixer) = - # call this inside audio thread - var bufferaddresses: seq[ptr SoundData] - for i in 0 ..< NBUFFERS: - mixer.buffers.add newSeq[Sample](BUFFERSAMPLECOUNT) - for i in 0 ..< mixer.buffers.len: - bufferaddresses.add (addr mixer.buffers[i]) - mixer.device = openSoundDevice(AUDIO_SAMPLE_RATE, bufferaddresses) - -proc loadSound*(mixer: var Mixer, name: string, resource: string) = - assert not (name in mixer.sounds) - mixer.sounds[name] = loadAudio(resource) - -proc addSound*(mixer: var Mixer, name: string, sound: Sound) = - assert not (name in mixer.sounds) - mixer.sounds[name] = sound - -proc replaceSound*(mixer: var Mixer, name: string, sound: Sound) = - assert (name in mixer.sounds) - mixer.sounds[name] = sound - -proc addTrack*(mixer: var Mixer, name: string, level: Level=1'f) = - assert not (name in mixer.tracks) - mixer.lock.withLock(): - mixer.tracks[name] = Track(level: level) - -proc play*(mixer: var Mixer, soundName: string, track="", stopOtherSounds=false, loop=false, levelLeft, levelRight: Level): uint64 = - assert track in mixer.tracks - assert soundName in mixer.sounds, soundName & " not loaded" - mixer.lock.withLock(): - if stopOtherSounds: - mixer.tracks[track].playing.clear() - mixer.tracks[track].playing[mixer.playbackCounter] = Playback( - sound: mixer.sounds[soundName], - position: 0, - loop: loop, - levelLeft: levelLeft, - levelRight: levelRight - ) - result = mixer.playbackCounter - inc mixer.playbackCounter - -proc play*(mixer: var Mixer, soundName: string, track="", stopOtherSounds=false, loop=false, level: Level=1'f): uint64 = - play( - mixer=mixer, - soundName=soundName, - track=track, - stopOtherSounds=stopOtherSounds, - loop=loop, - levelLeft=level, - levelRight=level - ) - -proc stop*(mixer: var Mixer) = - mixer.lock.withLock(): - for track in mixer.tracks.mvalues: - track.playing.clear() - -proc getLevel*(mixer: var Mixer): Level = mixer.level -proc getLevel*(mixer: var Mixer, track: string): Level = mixer.tracks[track].level -proc getLevel*(mixer: var Mixer, playbackId : uint64): (Level, Level) = - for track in mixer.tracks.mvalues: - if playbackId in track.playing: - return (track.playing[playbackId].levelLeft, track.playing[playbackId].levelRight) - -proc setLevel*(mixer: var Mixer, level: Level) = mixer.level = level -proc setLevel*(mixer: var Mixer, track: string, level: Level) = - mixer.lock.withLock(): - mixer.tracks[track].level = level -proc setLevel*(mixer: var Mixer, playbackId: uint64, levelLeft, levelRight: Level) = - mixer.lock.withLock(): - for track in mixer.tracks.mvalues: - if playbackId in track.playing: - track.playing[playbackId].levelLeft = levelLeft - track.playing[playbackId].levelRight = levelRight -proc setLevel*(mixer: var Mixer, playbackId : uint64, level: Level) = - setLevel(mixer, playbackId, level, level) - -proc stop*(mixer: var Mixer, track: string) = - assert track in mixer.tracks - mixer.lock.withLock(): - mixer.tracks[track].playing.clear() - -proc stop*(mixer: var Mixer, playbackId: uint64) = - mixer.lock.withLock(): - for track in mixer.tracks.mvalues: - if playbackId in track.playing: - track.playing.del(playbackId) - break - -proc isPlaying*(mixer: var Mixer): bool = - mixer.lock.withLock(): - for track in mixer.tracks.mvalues: - if track.playing.len > 0: - return true - return false - -proc isPlaying*(mixer: var Mixer, track: string): bool = - mixer.lock.withLock(): - return mixer.tracks.contains(track) and mixer.tracks[track].playing.len > 0 - -func applyLevel(sample: Sample, levelLeft, levelRight: Level): Sample = - [int16(float(sample[0]) * levelLeft), int16(float(sample[1]) * levelRight)] - -func clip(value: int32): int16 = - int16(max(min(int32(high(int16)), value), int32(low(int16)))) - -# used for combining sounds -func mix(a, b: Sample): Sample = - [ - clip(int32(a[0]) + int32(b[0])), - clip(int32(a[1]) + int32(b[1])), - ] - -proc updateSoundBuffer(mixer: var Mixer) = - # mix - for i in 0 ..< mixer.buffers[mixer.currentBuffer].len: - var currentSample = [0'i16, 0'i16] - mixer.lock.withLock(): - for track in mixer.tracks.mvalues: - var stoppedSounds: seq[uint64] - for (id, playback) in track.playing.mpairs: - let sample = applyLevel( - playback.sound[][playback.position], - mixer.level * track.level * playback.levelLeft, - mixer.level * track.level * playback.levelRight, - ) - currentSample = mix(currentSample, sample) - inc playback.position - if playback.position >= playback.sound[].len: - if playback.loop: - playback.position = 0 - else: - stoppedSounds.add id - for id in stoppedSounds: - track.playing.del(id) - mixer.buffers[mixer.currentBuffer][i] = currentSample - # send data to sound device - mixer.device.writeSoundData(mixer.currentBuffer) - mixer.currentBuffer = (mixer.currentBuffer + 1) mod mixer.buffers.len - - -proc destroy*(mixer: var Mixer) = - mixer.lock.deinitLock() - mixer.device.closeSoundDevice() - -# Threaded implementation, usually used for audio - -var - mixer* = createShared(Mixer) - audiothread: Thread[void] - -proc audioWorker() {.thread.} = - mixer[].setupDevice() - onThreadDestruction(proc() = mixer[].lock.withLock(mixer[].destroy()); freeShared(mixer)) - while true: - mixer[].updateSoundBuffer() - -proc startMixerThread*() = - mixer[] = initMixer() - audiothread.createThread(audioWorker) - debug "Created audio thread" - when defined(window): - SetThreadPriority(audiothread.handle(), THREAD_PRIORITY_TIME_CRITICAL) - when defined(linux): - discard pthread_setschedprio(Pthread(audiothread.handle()), cint(-20)) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/collision.nim --- a/src/semicongine/collision.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,386 +0,0 @@ -import ./core - -const MAX_COLLISON_DETECTION_ITERATIONS = 20 -const MAX_COLLISON_POINT_CALCULATION_ITERATIONS = 20 - -type - ColliderType* = enum - Box, Sphere, Points - Collider* = object - transform*: Mat4 = Unit4F32 - case theType*: ColliderType - of Box: discard - of Sphere: radius*: float32 - of Points: points*: seq[Vec3f] - -func between(value, b1, b2: float32): bool = - min(b1, b2) <= value and value <= max(b1, b2) - -func contains*(collider: Collider, x: Vec3f): bool = - # from https://math.stackexchange.com/questions/1472049/check-if-a-point-is-inside-a-rectangular-shaped-area-3d - case collider.theType: - of Box: - let - P1 = collider.transform * newVec3f(0, 0, 0) # origin - P2 = collider.transform * Z - P4 = collider.transform * X - P5 = collider.transform * Y - u = (P1 - P4).cross(P1 - P5) - v = (P1 - P2).cross(P1 - P5) - w = (P1 - P2).cross(P1 - P4) - uP1 = u.dot(P1) - uP2 = u.dot(P2) - vP1 = v.dot(P1) - vP4 = v.dot(P4) - wP1 = w.dot(P1) - wP5 = w.dot(P5) - ux = u.dot(x) - vx = v.dot(x) - wx = w.dot(x) - ux.between(uP1, uP2) and vx.between(vP1, vP4) and wx.between(wP1, wP5) - of Sphere: - (collider.transform * x).length < (collider.transform * newVec3f()).length - of Points: - raise newException(Exception, "Points are not supported yet for 'contains'") - -# implementation of GJK, based on https://blog.winter.dev/2020/gjk-algorithm/ - -# most generic implementation of findFurthestPoint -# add other implementations of findFurthestPoint for other kind of geometry or optimization -# (will be selected depening on type of the first parameter) -func findFurthestPoint(points: openArray[Vec3f], direction: Vec3f): Vec3f = - var maxDist = low(float32) - for p in points: - let dist = direction.dot(p) - if dist > maxDist: - maxDist = dist - result = p - -func findFurthestPoint(transform: Mat4, direction: Vec3f): Vec3f = - return findFurthestPoint( - [ - transform * newVec3f(0, 0, 0), - transform * X, - transform * Y, - transform * Z, - transform * (X + Y), - transform * (X + Z), - transform * (Y + Z), - transform * (X + Y + Z), - ], - direction - ) -func findFurthestPoint(collider: Collider, direction: Vec3f): Vec3f = - case collider.theType - of Sphere: - let directionNormalizedToSphere = ((direction / direction.length) * collider.radius) - collider.transform * directionNormalizedToSphere - of Box: - findFurthestPoint(collider.transform, direction) - of Points: - findFurthestPoint(collider.points, direction) - -func supportPoint(a, b: Collider, direction: Vec3f): Vec3f = - a.findFurthestPoint(direction) - b.findFurthestPoint(-direction) - -func sameDirection(direction: Vec3f, ao: Vec3f): bool = - direction.dot(ao) > 0 - -func line(simplex: var seq[Vec3f], direction: var Vec3f): bool = - let - a = simplex[0] - b = simplex[1] - ab = b - a - ao = - a - - if sameDirection(ab, ao): - direction = cross(cross(ab, ao), ab) - else: - simplex = @[a] - direction = ao - - return false - -func triangle(simplex: var seq[Vec3f], direction: var Vec3f, twoDimensional=false): bool = - let - a = simplex[0] - b = simplex[1] - c = simplex[2] - ab = b - a - ac = c - a - ao = - a - abc = ab.cross(ac) - - if sameDirection(abc.cross(ac), ao): - if sameDirection(ac, ao): - simplex = @[a, c] - direction = ac.cross(ao).cross(ac) - else: - simplex = @[a, b] - return line(simplex, direction) - else: - if (sameDirection(ab.cross(abc), ao)): - simplex = @[a, b] - return line(simplex, direction) - else: - if twoDimensional: - return true - if (sameDirection(abc, ao)): - direction = abc - else: - simplex = @[ a, c, b] - direction = -abc - - return false - -func tetrahedron(simplex: var seq[Vec3f], direction: var Vec3f): bool = - let - a = simplex[0] - b = simplex[1] - c = simplex[2] - d = simplex[3] - ab = b - a - ac = c - a - ad = d - a - ao = - a - abc = ab.cross(ac) - acd = ac.cross(ad) - adb = ad.cross(ab) - - if sameDirection(abc, ao): - simplex = @[a, b, c] - return triangle(simplex, direction) - if sameDirection(acd, ao): - simplex = @[a, c, d] - return triangle(simplex, direction) - if sameDirection(adb, ao): - simplex = @[a, d, b] - return triangle(simplex, direction) - - return true - -func getFaceNormals(polytope: seq[Vec3f], faces: seq[int]): (seq[Vec4f], int) = - var - normals: seq[Vec4f] - minTriangle = 0 - minDistance = high(float32) - - for i in countup(0, faces.len - 1, 3): - let - a = polytope[faces[i + 0]] - b = polytope[faces[i + 1]] - c = polytope[faces[i + 2]] - - var normal = (b - a).cross(c - a).normalized() - var distance = normal.dot(a) - - if distance < 0: - normal = normal * -1'f32 - distance = distance * -1'f32 - - normals.add normal.toVec4(distance) - - if distance < minDistance: - minTriangle = i div 3 - minDistance = distance - - return (normals, minTriangle) - -func addIfUniqueEdge(edges: var seq[(int, int)], faces: seq[int], a: int, b: int) = - let reverse = edges.find((faces[b], faces[a])) - if (reverse >= 0): - edges.delete(reverse) - else: - edges.add (faces[a], faces[b]) - -func nextSimplex(simplex: var seq[Vec3f], direction: var Vec3f, twoDimensional=false): bool = - case simplex.len - of 2: simplex.line(direction) - of 3: simplex.triangle(direction, twoDimensional) - of 4: simplex.tetrahedron(direction) - else: raise newException(Exception, "Error in simplex") - -func collisionPoint3D(simplex: var seq[Vec3f], a, b: Collider): tuple[normal: Vec3f, penetrationDepth: float32] = - var - polytope = simplex - faces = @[ - 0, 1, 2, - 0, 3, 1, - 0, 2, 3, - 1, 3, 2 - ] - (normals, minFace) = getFaceNormals(polytope, faces) - minNormal: Vec3f - minDistance = high(float32) - iterCount = 0 - - while minDistance == high(float32) and iterCount < MAX_COLLISON_POINT_CALCULATION_ITERATIONS: - minNormal = normals[minFace].xyz - minDistance = normals[minFace].w - var - support = supportPoint(a, b, minNormal) - sDistance = minNormal.dot(support) - - if abs(sDistance - minDistance) > 0.001'f32: - minDistance = high(float32) - var uniqueEdges: seq[(int, int)] - var i = 0 - while i < normals.len: - if sameDirection(normals[i], support): - var f = i * 3 - - addIfUniqueEdge(uniqueEdges, faces, f + 0, f + 1) - addIfUniqueEdge(uniqueEdges, faces, f + 1, f + 2) - addIfUniqueEdge(uniqueEdges, faces, f + 2, f + 0) - - faces[f + 2] = faces.pop() - faces[f + 1] = faces.pop() - faces[f + 0] = faces.pop() - - normals[i] = normals.pop() - - dec i - inc i - - var newFaces: seq[int] - for (edgeIndex1, edgeIndex2) in uniqueEdges: - newFaces.add edgeIndex1 - newFaces.add edgeIndex2 - newFaces.add polytope.len - - polytope.add support - - var (newNormals, newMinFace) = getFaceNormals(polytope, newFaces) - if newNormals.len == 0: - break - - var oldMinDistance = high(float32) - for j in 0 ..< normals.len: - if normals[j].w < oldMinDistance: - oldMinDistance = normals[j].w - minFace = j - - if (newNormals[newMinFace].w < oldMinDistance): - minFace = newMinFace + normals.len - - for f in newFaces: - faces.add f - for n in newNormals: - normals.add n - inc iterCount - - result = (normal: minNormal, penetrationDepth: minDistance + 0.001'f32) - - -func collisionPoint2D(polytopeIn: seq[Vec3f], a, b: Collider): tuple[normal: Vec3f, penetrationDepth: float32] = - var - polytope = polytopeIn - minIndex = 0 - minDistance = high(float32) - iterCount = 0 - minNormal: Vec2f - - while minDistance == high(float32) and iterCount < MAX_COLLISON_POINT_CALCULATION_ITERATIONS: - for i in 0 ..< polytope.len: - let - j = (i + 1) mod polytope.len - vertexI = polytope[i] - vertexJ = polytope[j] - ij = vertexJ - vertexI - var - normal = newVec2f(ij.y, -ij.x).normalized() - distance = normal.dot(vertexI) - - if (distance < 0): - distance *= -1'f32 - normal = normal * -1'f32 - - if distance < minDistance: - minDistance = distance - minNormal = normal - minIndex = j - - let - support = supportPoint(a, b, minNormal.toVec3) - sDistance = minNormal.dot(support) - - if(abs(sDistance - minDistance) > 0.001): - minDistance = high(float32) - polytope.insert(support, minIndex) - inc iterCount - - result = (normal: newVec3f(minNormal.x, minNormal.y), penetrationDepth: minDistance + 0.001'f32) - -func intersects*(a, b: Collider, as2D=false): bool = - var - support = supportPoint(a, b, newVec3f(0.8153, -0.4239, if as2D: 0.0 else: 0.5786)) # just random initial vector - simplex = newSeq[Vec3f]() - direction = -support - n = 0 - simplex.insert(support, 0) - while n < MAX_COLLISON_DETECTION_ITERATIONS: - support = supportPoint(a, b, direction) - if support.dot(direction) <= 0: - return false - simplex.insert(support, 0) - if nextSimplex(simplex, direction, twoDimensional=as2D): - return true - # prevent numeric instability - if direction == newVec3f(0, 0, 0): - direction[0] = 0.0001 - inc n - -func collision*(a, b: Collider, as2D=false): tuple[hasCollision: bool, normal: Vec3f, penetrationDepth: float32] = - var - support = supportPoint(a, b, newVec3f(0.8153, -0.4239, if as2D: 0.0 else: 0.5786)) # just random initial vector - simplex = newSeq[Vec3f]() - direction = -support - n = 0 - simplex.insert(support, 0) - while n < MAX_COLLISON_DETECTION_ITERATIONS: - support = supportPoint(a, b, direction) - if support.dot(direction) <= 0: - return result - simplex.insert(support, 0) - if nextSimplex(simplex, direction, twoDimensional=as2D): - let (normal, depth) = if as2D: collisionPoint2D(simplex, a, b) else: collisionPoint3D(simplex, a, b) - return (true, normal, depth) - # prevent numeric instability - if direction == newVec3f(0, 0, 0): - direction[0] = 0.0001 - inc n - -func calculateCollider*(points: openArray[Vec3f], theType: ColliderType): Collider = - var - minX = high(float32) - maxX = low(float32) - minY = high(float32) - maxY = low(float32) - minZ = high(float32) - maxZ = low(float32) - center: Vec3f - - for p in points: - minX = min(minX, p.x) - maxX = max(maxX, p.x) - minY = min(minY, p.y) - maxY = max(maxY, p.y) - minZ = min(minZ, p.z) - maxZ = max(maxz, p.z) - center = center + p - center = center / float32(points.len) - - let - scaleX = (maxX - minX) - scaleY = (maxY - minY) - scaleZ = (maxZ - minZ) - - if theType == Points: - result = Collider(theType: Points, points: @points) - else: - result = Collider(theType: theType, transform: translate(minX, minY, minZ) * scale(scaleX, scaleY, scaleZ)) - - if theType == Sphere: - result.transform = translate(center) - for p in points: - result.radius = max(result.radius, (p - center).length) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core.nim --- a/src/semicongine/core.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -import std/math -export math - -import ./core/audiotypes -import ./core/fonttypes -import ./core/vulkanapi -import ./core/buildconfig -import ./core/color -import ./core/gpu_types -import ./core/dynamic_arrays -import ./core/imagetypes -import ./core/matrix -import ./core/vector -import ./core/utils - -export vulkanapi -export audiotypes -export fonttypes -export buildconfig -export color -export gpu_types -export dynamic_arrays -export imagetypes -export matrix -export vector -export utils diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/audiotypes.nim --- a/src/semicongine/core/audiotypes.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -import std/math - -# in order to generate sound files that are directly usable with the engine, -# convert an audio file to a raw PCM signed 16 bit little endian file with 2 channels and 48kHz: -# -# ffmpeg -i -f s16le -ac 2 -ar 44100 -acodec pcm_s16le - -const AUDIO_SAMPLE_RATE* = 44100 - -type - Level* = 0'f .. 1'f - Sample* = array[2, int16] - SoundData* = seq[Sample] - Sound* = ref SoundData - -proc sinewave(f: float): proc(x: float): float = - proc ret(x: float): float = - sin(x * 2 * Pi * f) - result = ret - -proc sineSoundData*(f: float, len: float, rate: int): SoundData = - let dt = 1'f / float(rate) - var sine = sinewave(f) - for i in 0 ..< int(float(rate) * len): - let t = dt * float(i) - let value = int16(sine(t) * float(high(int16))) - result.add [value, value] - -proc newSound*(data: SoundData): Sound = - result = new Sound - result[] = data diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/buildconfig.nim --- a/src/semicongine/core/buildconfig.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -import std/parsecfg -import std/streams -import std/strutils -import std/logging -import std/os - -const ENGINENAME* = "semicongine" -const ENGINEVERSION* = static: - let nimblePath = currentSourcePath.parentDir().parentDir().parentDir().joinPath("semicongine.nimble") - let nimbleFile = newStringStream(staticRead(nimblePath)) - let config = loadConfig(nimbleFile) - config.getSectionValue("", "version") - - -# checks required build options: -static: - assert compileOption("threads"), ENGINENAME & " requires --threads=on" - assert defined(nimPreviewHashRef), ENGINENAME & " requires -d:nimPreviewHashRef" - - if defined(release): - assert compileOption("app", "gui"), ENGINENAME & " requires --app=gui for release builds" - - - if defined(linux): - assert defined(VK_USE_PLATFORM_XLIB_KHR), ENGINENAME & " requires --d:VK_USE_PLATFORM_XLIB_KHR for linux builds" - elif defined(windows): - assert defined(VK_USE_PLATFORM_WIN32_KHR), ENGINENAME & " requires --d:VK_USE_PLATFORM_WIN32_KHR for windows builds" - else: - assert false, "trying to build on unsupported platform" - -# build configuration -# ===================== - -# compile-time defines, usefull for build-dependent settings -# can be overriden with compiler flags, e.g. -d:Foo=42 -d:Bar=false -# pramas: {.intdefine.} {.strdefine.} {.booldefine.} - -# root of where settings files will be searched -# must be relative (to the directory of the binary) -const DEBUG* = not defined(release) -const CONFIGROOT* {.strdefine.}: string = "." -assert not isAbsolute(CONFIGROOT) - -const CONFIGEXTENSION* {.strdefine.}: string = "ini" - -# by default enable hot-reload of runtime-configuration only in debug builds -const CONFIGHOTRELOAD* {.booldefine.}: bool = DEBUG - -# milliseconds to wait between checks for settings hotreload -const CONFIGHOTRELOADINTERVAL* {.intdefine.}: int = 1000 - -# log level -const LOGLEVEL {.strdefine.}: string = (when DEBUG: "lvlWarn" else: "lvlWarn") -const ENGINE_LOGLEVEL* = parseEnum[Level](LOGLEVEL) - -# resource bundleing settings, need to be configured per project -const RESOURCEROOT* {.strdefine.}: string = "" # should be the "mod" directory -const BUNDLETYPE* {.strdefine.}: string = "" # dir, zip, exe - -static: - assert RESOURCEROOT != "", ENGINENAME & " requires -d:RESOURCEROOT=resources" - assert BUNDLETYPE in ["dir", "zip", "exe"], ENGINENAME & " requires one of -d:BUNDLETYPE=dir -d:BUNDLETYPE=zip -d:BUNDLETYPE=exe" diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/color.nim --- a/src/semicongine/core/color.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -import std/parseutils -import std/strformat - -import ./vector - - -func colorToHex*(color: Vec3f): string = - &"{int(color.r * 255):02X}{int(color.g * 255):02X}{int(color.b * 255):02X}" - -func colorToHex*(color: Vec4f): string = - &"{int(color.r * 255):02X}{int(color.g * 255):02X}{int(color.b * 255):02X}{int(color.a * 255):02X}" - -func asPixel*(color: Vec3f): array[4, uint8] = - [uint8(color.r * 255), uint8(color.g * 255), uint8(color.b * 255), 255'u8] -func asPixel*(color: Vec4f): array[4, uint8] = - [uint8(color.r * 255), uint8(color.g * 255), uint8(color.b * 255), uint8(color.a * 255)] - -func toRGBA*(value: string): Vec4f = - assert value != "" - var hex = value - if hex[0] == '#': - hex = hex[1 .. ^1] - # when 3 or 6 -> set alpha to 1.0 - assert hex.len == 3 or hex.len == 6 or hex.len == 4 or hex.len == 8 - if hex.len == 3: - hex = hex & "f" - if hex.len == 4: - hex = hex[0] & hex[0] & hex[1] & hex[1] & hex[2] & hex[2] & hex[3] & hex[3] - if hex.len == 6: - hex = hex & "ff" - assert hex.len == 8 - var r, g, b, a: uint8 - discard parseHex(hex[0 .. 1], r) - discard parseHex(hex[2 .. 3], g) - discard parseHex(hex[4 .. 5], b) - discard parseHex(hex[6 .. 7], a) - return Vec4f([float32(r), float32(g), float32(b), float32(a)]) / 255'f - -func gamma*[T: Vec3f|Vec4f](color: T, gamma: float32): T = - return pow(color, gamma) - -const - Black* = toRGBA "#000000FF" - Silver* = toRGBA "#C0C0C0FF" - Gray* = toRGBA "#808080FF" - White* = toRGBA "#FFFFFFFF" - Maroon* = toRGBA "#800000FF" - Red* = toRGBA "#FF0000FF" - Purple* = toRGBA "#800080FF" - Fuchsia* = toRGBA "#FF00FFFF" - Green* = toRGBA "#008000FF" - Lime* = toRGBA "#00FF00FF" - Olive* = toRGBA "#808000FF" - Yellow* = toRGBA "#FFFF00FF" - Navy* = toRGBA "#000080FF" - Blue* = toRGBA "#0000FFFF" - Teal* = toRGBA "#008080FF" - Aqua* = toRGBA "#00FFFFFF" diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/dynamic_arrays.nim --- a/src/semicongine/core/dynamic_arrays.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,765 +0,0 @@ -import std/hashes - -import ./gpu_types -import ./vector -import ./matrix -import ./utils -import ./imagetypes - -type - DataList* = object - len*: int - case theType*: DataType - of Float32: float32: ref seq[float32] - of Float64: float64: ref seq[float64] - of Int8: int8: ref seq[int8] - of Int16: int16: ref seq[int16] - of Int32: int32: ref seq[int32] - of Int64: int64: ref seq[int64] - of UInt8: uint8: ref seq[uint8] - of UInt16: uint16: ref seq[uint16] - of UInt32: uint32: ref seq[uint32] - of UInt64: uint64: ref seq[uint64] - of Vec2I32: vec2i32: ref seq[TVec2[int32]] - of Vec2I64: vec2i64: ref seq[TVec2[int64]] - of Vec3I32: vec3i32: ref seq[TVec3[int32]] - of Vec3I64: vec3i64: ref seq[TVec3[int64]] - of Vec4I32: vec4i32: ref seq[TVec4[int32]] - of Vec4I64: vec4i64: ref seq[TVec4[int64]] - of Vec2U32: vec2u32: ref seq[TVec2[uint32]] - of Vec2U64: vec2u64: ref seq[TVec2[uint64]] - of Vec3U32: vec3u32: ref seq[TVec3[uint32]] - of Vec3U64: vec3u64: ref seq[TVec3[uint64]] - of Vec4U32: vec4u32: ref seq[TVec4[uint32]] - of Vec4U64: vec4u64: ref seq[TVec4[uint64]] - of Vec2F32: vec2f32: ref seq[TVec2[float32]] - of Vec2F64: vec2f64: ref seq[TVec2[float64]] - of Vec3F32: vec3f32: ref seq[TVec3[float32]] - of Vec3F64: vec3f64: ref seq[TVec3[float64]] - of Vec4F32: vec4f32: ref seq[TVec4[float32]] - of Vec4F64: vec4f64: ref seq[TVec4[float64]] - of Mat2F32: mat2f32: ref seq[TMat2[float32]] - of Mat2F64: mat2f64: ref seq[TMat2[float64]] - of Mat23F32: mat23f32: ref seq[TMat23[float32]] - of Mat23F64: mat23f64: ref seq[TMat23[float64]] - of Mat32F32: mat32f32: ref seq[TMat32[float32]] - of Mat32F64: mat32f64: ref seq[TMat32[float64]] - of Mat3F32: mat3f32: ref seq[TMat3[float32]] - of Mat3F64: mat3f64: ref seq[TMat3[float64]] - of Mat34F32: mat34f32: ref seq[TMat34[float32]] - of Mat34F64: mat34f64: ref seq[TMat34[float64]] - of Mat43F32: mat43f32: ref seq[TMat43[float32]] - of Mat43F64: mat43f64: ref seq[TMat43[float64]] - of Mat4F32: mat4f32: ref seq[TMat4[float32]] - of Mat4F64: mat4f64: ref seq[TMat4[float64]] - of TextureType: texture: ref seq[Texture] - -func size*(value: DataList): int = - value.theType.size * value.len - -func hash*(value: DataList): Hash = - case value.theType - of Float32: hash(value.float32) - of Float64: hash(value.float64) - of Int8: hash(value.int8) - of Int16: hash(value.int16) - of Int32: hash(value.int32) - of Int64: hash(value.int64) - of UInt8: hash(value.uint8) - of UInt16: hash(value.uint16) - of UInt32: hash(value.uint32) - of UInt64: hash(value.uint64) - of Vec2I32: hash(value.vec2i32) - of Vec2I64: hash(value.vec2i64) - of Vec3I32: hash(value.vec3i32) - of Vec3I64: hash(value.vec3i64) - of Vec4I32: hash(value.vec4i32) - of Vec4I64: hash(value.vec4i64) - of Vec2U32: hash(value.vec2u32) - of Vec2U64: hash(value.vec2u64) - of Vec3U32: hash(value.vec3u32) - of Vec3U64: hash(value.vec3u64) - of Vec4U32: hash(value.vec4u32) - of Vec4U64: hash(value.vec4u64) - of Vec2F32: hash(value.vec2f32) - of Vec2F64: hash(value.vec2f64) - of Vec3F32: hash(value.vec3f32) - of Vec3F64: hash(value.vec3f64) - of Vec4F32: hash(value.vec4f32) - of Vec4F64: hash(value.vec4f64) - of Mat2F32: hash(value.mat2f32) - of Mat2F64: hash(value.mat2f64) - of Mat23F32: hash(value.mat23f32) - of Mat23F64: hash(value.mat23f64) - of Mat32F32: hash(value.mat32f32) - of Mat32F64: hash(value.mat32f64) - of Mat3F32: hash(value.mat3f32) - of Mat3F64: hash(value.mat3f64) - of Mat34F32: hash(value.mat34f32) - of Mat34F64: hash(value.mat34f64) - of Mat43F32: hash(value.mat43f32) - of Mat43F64: hash(value.mat43f64) - of Mat4F32: hash(value.mat4f32) - of Mat4F64: hash(value.mat4f64) - of TextureType: hash(value.texture) - -func `==`*(a, b: DataList): bool = - if a.theType != b.theType: - return false - case a.theType - of Float32: return a.float32 == b.float32 - of Float64: return a.float64 == b.float64 - of Int8: return a.int8 == b.int8 - of Int16: return a.int16 == b.int16 - of Int32: return a.int32 == b.int32 - of Int64: return a.int64 == b.int64 - of UInt8: return a.uint8 == b.uint8 - of UInt16: return a.uint16 == b.uint16 - of UInt32: return a.uint32 == b.uint32 - of UInt64: return a.uint64 == b.uint64 - of Vec2I32: return a.vec2i32 == b.vec2i32 - of Vec2I64: return a.vec2i64 == b.vec2i64 - of Vec3I32: return a.vec3i32 == b.vec3i32 - of Vec3I64: return a.vec3i64 == b.vec3i64 - of Vec4I32: return a.vec4i32 == b.vec4i32 - of Vec4I64: return a.vec4i64 == b.vec4i64 - of Vec2U32: return a.vec2u32 == b.vec2u32 - of Vec2U64: return a.vec2u64 == b.vec2u64 - of Vec3U32: return a.vec3u32 == b.vec3u32 - of Vec3U64: return a.vec3u64 == b.vec3u64 - of Vec4U32: return a.vec4u32 == b.vec4u32 - of Vec4U64: return a.vec4u64 == b.vec4u64 - of Vec2F32: return a.vec2f32 == b.vec2f32 - of Vec2F64: return a.vec2f64 == b.vec2f64 - of Vec3F32: return a.vec3f32 == b.vec3f32 - of Vec3F64: return a.vec3f64 == b.vec3f64 - of Vec4F32: return a.vec4f32 == b.vec4f32 - of Vec4F64: return a.vec4f64 == b.vec4f64 - of Mat2F32: return a.mat2f32 == b.mat2f32 - of Mat2F64: return a.mat2f64 == b.mat2f64 - of Mat23F32: return a.mat23f32 == b.mat23f32 - of Mat23F64: return a.mat23f64 == b.mat23f64 - of Mat32F32: return a.mat32f32 == b.mat32f32 - of Mat32F64: return a.mat32f64 == b.mat32f64 - of Mat3F32: return a.mat3f32 == b.mat3f32 - of Mat3F64: return a.mat3f64 == b.mat3f64 - of Mat34F32: return a.mat34f32 == b.mat34f32 - of Mat34F64: return a.mat34f64 == b.mat34f64 - of Mat43F32: return a.mat43f32 == b.mat43f32 - of Mat43F64: return a.mat43f64 == b.mat43f64 - of Mat4F32: return a.mat4f32 == b.mat4f32 - of Mat4F64: return a.mat4f64 == b.mat4f64 - of TextureType: a.texture == b.texture - -proc setLen*(value: var DataList, len: int) = - value.len = len - case value.theType - of Float32: value.float32[].setLen(len) - of Float64: value.float64[].setLen(len) - of Int8: value.int8[].setLen(len) - of Int16: value.int16[].setLen(len) - of Int32: value.int32[].setLen(len) - of Int64: value.int64[].setLen(len) - of UInt8: value.uint8[].setLen(len) - of UInt16: value.uint16[].setLen(len) - of UInt32: value.uint32[].setLen(len) - of UInt64: value.uint64[].setLen(len) - of Vec2I32: value.vec2i32[].setLen(len) - of Vec2I64: value.vec2i64[].setLen(len) - of Vec3I32: value.vec3i32[].setLen(len) - of Vec3I64: value.vec3i64[].setLen(len) - of Vec4I32: value.vec4i32[].setLen(len) - of Vec4I64: value.vec4i64[].setLen(len) - of Vec2U32: value.vec2u32[].setLen(len) - of Vec2U64: value.vec2u64[].setLen(len) - of Vec3U32: value.vec3u32[].setLen(len) - of Vec3U64: value.vec3u64[].setLen(len) - of Vec4U32: value.vec4u32[].setLen(len) - of Vec4U64: value.vec4u64[].setLen(len) - of Vec2F32: value.vec2f32[].setLen(len) - of Vec2F64: value.vec2f64[].setLen(len) - of Vec3F32: value.vec3f32[].setLen(len) - of Vec3F64: value.vec3f64[].setLen(len) - of Vec4F32: value.vec4f32[].setLen(len) - of Vec4F64: value.vec4f64[].setLen(len) - of Mat2F32: value.mat2f32[].setLen(len) - of Mat2F64: value.mat2f64[].setLen(len) - of Mat23F32: value.mat23f32[].setLen(len) - of Mat23F64: value.mat23f64[].setLen(len) - of Mat32F32: value.mat32f32[].setLen(len) - of Mat32F64: value.mat32f64[].setLen(len) - of Mat3F32: value.mat3f32[].setLen(len) - of Mat3F64: value.mat3f64[].setLen(len) - of Mat34F32: value.mat34f32[].setLen(len) - of Mat34F64: value.mat34f64[].setLen(len) - of Mat43F32: value.mat43f32[].setLen(len) - of Mat43F64: value.mat43f64[].setLen(len) - of Mat4F32: value.mat4f32[].setLen(len) - of Mat4F64: value.mat4f64[].setLen(len) - of TextureType: discard - - -proc setValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = - value.setLen(data.len) - when T is float32: value.float32[] = data - elif T is float64: value.float64[] = data - elif T is int8: value.int8[] = data - elif T is int16: value.int16[] = data - elif T is int32: value.int32[] = data - elif T is int64: value.int64[] = data - elif T is uint8: value.uint8[] = data - elif T is uint16: value.uint16[] = data - elif T is uint32: value.uint32[] = data - elif T is uint64: value.uint64[] = data - elif T is int and sizeof(int) == sizeof(int32): value.int32[] = data - elif T is int and sizeof(int) == sizeof(int64): value.int64[] = data - elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[] = data - elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[] = data - elif T is float and sizeof(float) == sizeof(float32): value.float32[] = data - elif T is float and sizeof(float) == sizeof(float64): value.float64[] = data - elif T is TVec2[int32]: value.vec2i32[] = data - elif T is TVec2[int64]: value.vec2i64[] = data - elif T is TVec3[int32]: value.vec3i32[] = data - elif T is TVec3[int64]: value.vec3i64[] = data - elif T is TVec4[int32]: value.vec4i32[] = data - elif T is TVec4[int64]: value.vec4i64[] = data - elif T is TVec2[uint32]: value.vec2u32[] = data - elif T is TVec2[uint64]: value.vec2u64[] = data - elif T is TVec3[uint32]: value.vec3u32[] = data - elif T is TVec3[uint64]: value.vec3u64[] = data - elif T is TVec4[uint32]: value.vec4u32[] = data - elif T is TVec4[uint64]: value.vec4u64[] = data - elif T is TVec2[float32]: value.vec2f32[] = data - elif T is TVec2[float64]: value.vec2f64[] = data - elif T is TVec3[float32]: value.vec3f32[] = data - elif T is TVec3[float64]: value.vec3f64[] = data - elif T is TVec4[float32]: value.vec4f32[] = data - elif T is TVec4[float64]: value.vec4f64[] = data - elif T is TMat2[float32]: value.mat2f32[] = data - elif T is TMat2[float64]: value.mat2f64[] = data - elif T is TMat23[float32]: value.mat23f32[] = data - elif T is TMat23[float64]: value.mat23f64[] = data - elif T is TMat32[float32]: value.mat32f32[] = data - elif T is TMat32[float64]: value.mat32f64[] = data - elif T is TMat3[float32]: value.mat3f32[] = data - elif T is TMat3[float64]: value.mat3f64[] = data - elif T is TMat34[float32]: value.mat34f32[] = data - elif T is TMat34[float64]: value.mat34f64[] = data - elif T is TMat43[float32]: value.mat43f32[] = data - elif T is TMat43[float64]: value.mat43f64[] = data - elif T is TMat4[float32]: value.mat4f32[] = data - elif T is TMat4[float64]: value.mat4f64[] = data - elif T is Texture: value.texture[] = data - else: {. error: "Virtual datatype has no values" .} - -proc initDataList*(theType: DataType, len=1): DataList = - result = DataList(theType: theType) - case result.theType - of Float32: result.float32 = new seq[float32] - of Float64: result.float64 = new seq[float64] - of Int8: result.int8 = new seq[int8] - of Int16: result.int16 = new seq[int16] - of Int32: result.int32 = new seq[int32] - of Int64: result.int64 = new seq[int64] - of UInt8: result.uint8 = new seq[uint8] - of UInt16: result.uint16 = new seq[uint16] - of UInt32: result.uint32 = new seq[uint32] - of UInt64: result.uint64 = new seq[uint64] - of Vec2I32: result.vec2i32 = new seq[TVec2[int32]] - of Vec2I64: result.vec2i64 = new seq[TVec2[int64]] - of Vec3I32: result.vec3i32 = new seq[TVec3[int32]] - of Vec3I64: result.vec3i64 = new seq[TVec3[int64]] - of Vec4I32: result.vec4i32 = new seq[TVec4[int32]] - of Vec4I64: result.vec4i64 = new seq[TVec4[int64]] - of Vec2U32: result.vec2u32 = new seq[TVec2[uint32]] - of Vec2U64: result.vec2u64 = new seq[TVec2[uint64]] - of Vec3U32: result.vec3u32 = new seq[TVec3[uint32]] - of Vec3U64: result.vec3u64 = new seq[TVec3[uint64]] - of Vec4U32: result.vec4u32 = new seq[TVec4[uint32]] - of Vec4U64: result.vec4u64 = new seq[TVec4[uint64]] - of Vec2F32: result.vec2f32 = new seq[TVec2[float32]] - of Vec2F64: result.vec2f64 = new seq[TVec2[float64]] - of Vec3F32: result.vec3f32 = new seq[TVec3[float32]] - of Vec3F64: result.vec3f64 = new seq[TVec3[float64]] - of Vec4F32: result.vec4f32 = new seq[TVec4[float32]] - of Vec4F64: result.vec4f64 = new seq[TVec4[float64]] - of Mat2F32: result.mat2f32 = new seq[TMat2[float32]] - of Mat2F64: result.mat2f64 = new seq[TMat2[float64]] - of Mat23F32: result.mat23f32 = new seq[TMat23[float32]] - of Mat23F64: result.mat23f64 = new seq[TMat23[float64]] - of Mat32F32: result.mat32f32 = new seq[TMat32[float32]] - of Mat32F64: result.mat32f64 = new seq[TMat32[float64]] - of Mat3F32: result.mat3f32 = new seq[TMat3[float32]] - of Mat3F64: result.mat3f64 = new seq[TMat3[float64]] - of Mat34F32: result.mat34f32 = new seq[TMat34[float32]] - of Mat34F64: result.mat34f64 = new seq[TMat34[float64]] - of Mat43F32: result.mat43f32 = new seq[TMat43[float32]] - of Mat43F64: result.mat43f64 = new seq[TMat43[float64]] - of Mat4F32: result.mat4f32 = new seq[TMat4[float32]] - of Mat4F64: result.mat4f64 = new seq[TMat4[float64]] - of TextureType: result.texture = new seq[Texture] - result.setLen(len) - -proc initDataList*[T: GPUType](len=1): DataList = - result = initDataList(getDataType[T]()) - result.setLen(len) - -proc initDataList*[T: GPUType](data: openArray[T]): DataList = - result = initDataList(getDataType[T]()) - result.setValues(@data) - -func getValues*[T: GPUType|int|uint|float](value: DataList): ref seq[T] = - when T is float32: value.float32 - elif T is float64: value.float64 - elif T is int8: value.int8 - elif T is int16: value.int16 - elif T is int32: value.int32 - elif T is int64: value.int64 - elif T is uint8: value.uint8 - elif T is uint16: value.uint16 - elif T is uint32: value.uint32 - elif T is uint64: value.uint64 - elif T is int and sizeof(int) == sizeof(int32): value.int32 - elif T is int and sizeof(int) == sizeof(int64): value.int64 - elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32 - elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64 - elif T is float and sizeof(float) == sizeof(float32): value.float32 - elif T is float and sizeof(float) == sizeof(float64): value.float64 - elif T is TVec2[int32]: value.vec2i32 - elif T is TVec2[int64]: value.vec2i64 - elif T is TVec3[int32]: value.vec3i32 - elif T is TVec3[int64]: value.vec3i64 - elif T is TVec4[int32]: value.vec4i32 - elif T is TVec4[int64]: value.vec4i64 - elif T is TVec2[uint32]: value.vec2u32 - elif T is TVec2[uint64]: value.vec2u64 - elif T is TVec3[uint32]: value.vec3u32 - elif T is TVec3[uint64]: value.vec3u64 - elif T is TVec4[uint32]: value.vec4u32 - elif T is TVec4[uint64]: value.vec4u64 - elif T is TVec2[float32]: value.vec2f32 - elif T is TVec2[float64]: value.vec2f64 - elif T is TVec3[float32]: value.vec3f32 - elif T is TVec3[float64]: value.vec3f64 - elif T is TVec4[float32]: value.vec4f32 - elif T is TVec4[float64]: value.vec4f64 - elif T is TMat2[float32]: value.mat2f32 - elif T is TMat2[float64]: value.mat2f64 - elif T is TMat23[float32]: value.mat23f - elif T is TMat23[float64]: value.mat23f64 - elif T is TMat32[float32]: value.mat32f32 - elif T is TMat32[float64]: value.mat32f64 - elif T is TMat3[float32]: value.mat3f32 - elif T is TMat3[float64]: value.mat3f64 - elif T is TMat34[float32]: value.mat34f32 - elif T is TMat34[float64]: value.mat34f64 - elif T is TMat43[float32]: value.mat43f32 - elif T is TMat43[float64]: value.mat43f64 - elif T is TMat4[float32]: value.mat4f32 - elif T is TMat4[float64]: value.mat4f64 - elif T is Texture: value.texture - else: {. error: "Virtual datatype has no values" .} - -func getValue*[T: GPUType|int|uint|float](value: DataList, i: int): T = - when T is float32: value.float32[i] - elif T is float64: value.float64[i] - elif T is int8: value.int8[i] - elif T is int16: value.int16[i] - elif T is int32: value.int32[i] - elif T is int64: value.int64[i] - elif T is uint8: value.uint8[i] - elif T is uint16: value.uint16[i] - elif T is uint32: value.uint32[i] - elif T is uint64: value.uint64[i] - elif T is int and sizeof(int) == sizeof(int32): value.int32[i] - elif T is int and sizeof(int) == sizeof(int64): value.int64[i] - elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[i] - elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[i] - elif T is float and sizeof(float) == sizeof(float32): value.float32[i] - elif T is float and sizeof(float) == sizeof(float64): value.float64[i] - elif T is TVec2[int32]: value.vec2i32[i] - elif T is TVec2[int64]: value.vec2i64[i] - elif T is TVec3[int32]: value.vec3i32[i] - elif T is TVec3[int64]: value.vec3i64[i] - elif T is TVec4[int32]: value.vec4i32[i] - elif T is TVec4[int64]: value.vec4i64[i] - elif T is TVec2[uint32]: value.vec2u32[i] - elif T is TVec2[uint64]: value.vec2u64[i] - elif T is TVec3[uint32]: value.vec3u32[i] - elif T is TVec3[uint64]: value.vec3u64[i] - elif T is TVec4[uint32]: value.vec4u32[i] - elif T is TVec4[uint64]: value.vec4u64[i] - elif T is TVec2[float32]: value.vec2f32[i] - elif T is TVec2[float64]: value.vec2f64[i] - elif T is TVec3[float32]: value.vec3f32[i] - elif T is TVec3[float64]: value.vec3f64[i] - elif T is TVec4[float32]: value.vec4f32[i] - elif T is TVec4[float64]: value.vec4f64[i] - elif T is TMat2[float32]: value.mat2f32[i] - elif T is TMat2[float64]: value.mat2f64[i] - elif T is TMat23[float32]: value.mat23f[i] - elif T is TMat23[float64]: value.mat23f64[i] - elif T is TMat32[float32]: value.mat32f32[i] - elif T is TMat32[float64]: value.mat32f64[i] - elif T is TMat3[float32]: value.mat3f32[i] - elif T is TMat3[float64]: value.mat3f64[i] - elif T is TMat34[float32]: value.mat34f32[i] - elif T is TMat34[float64]: value.mat34f64[i] - elif T is TMat43[float32]: value.mat43f32[i] - elif T is TMat43[float64]: value.mat43f64[i] - elif T is TMat4[float32]: value.mat4f32[i] - elif T is TMat4[float64]: value.mat4f64[i] - elif T is Texture: value.texture[i] - else: {. error: "Virtual datatype has no values" .} - -func getRawData*(value: var DataList): (pointer, int) = - if value.len == 0: - return (nil, 0) - result[1] = value.theType.size * value.len - case value.theType - of Float32: result[0] = value.float32[].toCPointer - of Float64: result[0] = value.float64[].toCPointer - of Int8: result[0] = value.int8[].toCPointer - of Int16: result[0] = value.int16[].toCPointer - of Int32: result[0] = value.int32[].toCPointer - of Int64: result[0] = value.int64[].toCPointer - of UInt8: result[0] = value.uint8[].toCPointer - of UInt16: result[0] = value.uint16[].toCPointer - of UInt32: result[0] = value.uint32[].toCPointer - of UInt64: result[0] = value.uint64[].toCPointer - of Vec2I32: result[0] = value.vec2i32[].toCPointer - of Vec2I64: result[0] = value.vec2i64[].toCPointer - of Vec3I32: result[0] = value.vec3i32[].toCPointer - of Vec3I64: result[0] = value.vec3i64[].toCPointer - of Vec4I32: result[0] = value.vec4i32[].toCPointer - of Vec4I64: result[0] = value.vec4i64[].toCPointer - of Vec2U32: result[0] = value.vec2u32[].toCPointer - of Vec2U64: result[0] = value.vec2u64[].toCPointer - of Vec3U32: result[0] = value.vec3u32[].toCPointer - of Vec3U64: result[0] = value.vec3u64[].toCPointer - of Vec4U32: result[0] = value.vec4u32[].toCPointer - of Vec4U64: result[0] = value.vec4u64[].toCPointer - of Vec2F32: result[0] = value.vec2f32[].toCPointer - of Vec2F64: result[0] = value.vec2f64[].toCPointer - of Vec3F32: result[0] = value.vec3f32[].toCPointer - of Vec3F64: result[0] = value.vec3f64[].toCPointer - of Vec4F32: result[0] = value.vec4f32[].toCPointer - of Vec4F64: result[0] = value.vec4f64[].toCPointer - of Mat2F32: result[0] = value.mat2f32[].toCPointer - of Mat2F64: result[0] = value.mat2f64[].toCPointer - of Mat23F32: result[0] = value.mat23f32[].toCPointer - of Mat23F64: result[0] = value.mat23f64[].toCPointer - of Mat32F32: result[0] = value.mat32f32[].toCPointer - of Mat32F64: result[0] = value.mat32f64[].toCPointer - of Mat3F32: result[0] = value.mat3f32[].toCPointer - of Mat3F64: result[0] = value.mat3f64[].toCPointer - of Mat34F32: result[0] = value.mat34f32[].toCPointer - of Mat34F64: result[0] = value.mat34f64[].toCPointer - of Mat43F32: result[0] = value.mat43f32[].toCPointer - of Mat43F64: result[0] = value.mat43f64[].toCPointer - of Mat4F32: result[0] = value.mat4f32[].toCPointer - of Mat4F64: result[0] = value.mat4f64[].toCPointer - of TextureType: result[0] = nil - -proc appendValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = - value.len += data.len - when T is float32: value.float32[].add data - elif T is float64: value.float64[].add data - elif T is int8: value.int8[].add data - elif T is int16: value.int16[].add data - elif T is int32: value.int32[].add data - elif T is int64: value.int64[].add data - elif T is uint8: value.uint8[].add data - elif T is uint16: value.uint16[].add data - elif T is uint32: value.uint32[].add data - elif T is uint64: value.uint64[].add data - elif T is int and sizeof(int) == sizeof(int32): value.int32[].add data - elif T is int and sizeof(int) == sizeof(int64): value.int64[].add data - elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[].add data - elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[].add data - elif T is float and sizeof(float) == sizeof(float32): value.float32[].add data - elif T is float and sizeof(float) == sizeof(float64): value.float64[].add data - elif T is TVec2[int32]: value.vec2i32[].add data - elif T is TVec2[int64]: value.vec2i64[].add data - elif T is TVec3[int32]: value.vec3i32[].add data - elif T is TVec3[int64]: value.vec3i64[].add data - elif T is TVec4[int32]: value.vec4i32[].add data - elif T is TVec4[int64]: value.vec4i64[].add data - elif T is TVec2[uint32]: value.vec2u32[].add data - elif T is TVec2[uint64]: value.vec2u64[].add data - elif T is TVec3[uint32]: value.vec3u32[].add data - elif T is TVec3[uint64]: value.vec3u64[].add data - elif T is TVec4[uint32]: value.vec4u32[].add data - elif T is TVec4[uint64]: value.vec4u64[].add data - elif T is TVec2[float32]: value.vec2f32[].add data - elif T is TVec2[float64]: value.vec2f64[].add data - elif T is TVec3[float32]: value.vec3f32[].add data - elif T is TVec3[float64]: value.vec3f64[].add data - elif T is TVec4[float32]: value.vec4f32[].add data - elif T is TVec4[float64]: value.vec4f64[].add data - elif T is TMat2[float32]: value.mat2f32[].add data - elif T is TMat2[float64]: value.mat2f64[].add data - elif T is TMat23[float32]: value.mat23f32[].add data - elif T is TMat23[float64]: value.mat23f64[].add data - elif T is TMat32[float32]: value.mat32f32[].add data - elif T is TMat32[float64]: value.mat32f64[].add data - elif T is TMat3[float32]: value.mat3f32[].add data - elif T is TMat3[float64]: value.mat3f64[].add data - elif T is TMat34[float32]: value.mat34f32[].add data - elif T is TMat34[float64]: value.mat34f64[].add data - elif T is TMat43[float32]: value.mat43f32[].add data - elif T is TMat43[float64]: value.mat43f64[].add data - elif T is TMat4[float32]: value.mat4f32[].add data - elif T is TMat4[float64]: value.mat4f64[].add data - elif T is Texture: value.texture[].add data - else: {. error: "Virtual datatype has no values" .} - -proc appendValues*(value: var DataList, data: DataList) = - assert value.theType == data.theType - value.len += data.len - case value.theType: - of Float32: value.float32[].add data.float32[] - of Float64: value.float64[].add data.float64[] - of Int8: value.int8[].add data.int8[] - of Int16: value.int16[].add data.int16[] - of Int32: value.int32[].add data.int32[] - of Int64: value.int64[].add data.int64[] - of UInt8: value.uint8[].add data.uint8[] - of UInt16: value.uint16[].add data.uint16[] - of UInt32: value.uint32[].add data.uint32[] - of UInt64: value.uint64[].add data.uint64[] - of Vec2I32: value.vec2i32[].add data.vec2i32[] - of Vec2I64: value.vec2i64[].add data.vec2i64[] - of Vec3I32: value.vec3i32[].add data.vec3i32[] - of Vec3I64: value.vec3i64[].add data.vec3i64[] - of Vec4I32: value.vec4i32[].add data.vec4i32[] - of Vec4I64: value.vec4i64[].add data.vec4i64[] - of Vec2U32: value.vec2u32[].add data.vec2u32[] - of Vec2U64: value.vec2u64[].add data.vec2u64[] - of Vec3U32: value.vec3u32[].add data.vec3u32[] - of Vec3U64: value.vec3u64[].add data.vec3u64[] - of Vec4U32: value.vec4u32[].add data.vec4u32[] - of Vec4U64: value.vec4u64[].add data.vec4u64[] - of Vec2F32: value.vec2f32[].add data.vec2f32[] - of Vec2F64: value.vec2f64[].add data.vec2f64[] - of Vec3F32: value.vec3f32[].add data.vec3f32[] - of Vec3F64: value.vec3f64[].add data.vec3f64[] - of Vec4F32: value.vec4f32[].add data.vec4f32[] - of Vec4F64: value.vec4f64[].add data.vec4f64[] - of Mat2F32: value.mat2f32[].add data.mat2f32[] - of Mat2F64: value.mat2f64[].add data.mat2f64[] - of Mat23F32: value.mat23f32[].add data.mat23f32[] - of Mat23F64: value.mat23f64[].add data.mat23f64[] - of Mat32F32: value.mat32f32[].add data.mat32f32[] - of Mat32F64: value.mat32f64[].add data.mat32f64[] - of Mat3F32: value.mat3f32[].add data.mat3f32[] - of Mat3F64: value.mat3f64[].add data.mat3f64[] - of Mat34F32: value.mat34f32[].add data.mat34f32[] - of Mat34F64: value.mat34f64[].add data.mat34f64[] - of Mat43F32: value.mat43f32[].add data.mat43f32[] - of Mat43F64: value.mat43f64[].add data.mat43f64[] - of Mat4F32: value.mat4f32[].add data.mat4f32[] - of Mat4F64: value.mat4f64[].add data.mat4f64[] - of TextureType: value.texture[].add data.texture[] - -proc setValue*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = - when T is float32: value.float32[] = data - elif T is float64: value.float64[] = data - elif T is int8: value.int8[] = data - elif T is int16: value.int16[] = data - elif T is int32: value.int32[] = data - elif T is int64: value.int64[] = data - elif T is uint8: value.uint8[] = data - elif T is uint16: value.uint16[] = data - elif T is uint32: value.uint32[] = data - elif T is uint64: value.uint64[] = data - elif T is int and sizeof(int) == sizeof(int32): value.int32[] = data - elif T is int and sizeof(int) == sizeof(int64): value.int64[] = data - elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[] = data - elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[] = data - elif T is float and sizeof(float) == sizeof(float32): value.float32[] = data - elif T is float and sizeof(float) == sizeof(float64): value.float64[] = data - elif T is TVec2[int32]: value.vec2i32[] = data - elif T is TVec2[int64]: value.vec2i64[] = data - elif T is TVec3[int32]: value.vec3i32[] = data - elif T is TVec3[int64]: value.vec3i64[] = data - elif T is TVec4[int32]: value.vec4i32[] = data - elif T is TVec4[int64]: value.vec4i64[] = data - elif T is TVec2[uint32]: value.vec2u32[] = data - elif T is TVec2[uint64]: value.vec2u64[] = data - elif T is TVec3[uint32]: value.vec3u32[] = data - elif T is TVec3[uint64]: value.vec3u64[] = data - elif T is TVec4[uint32]: value.vec4u32[] = data - elif T is TVec4[uint64]: value.vec4u64[] = data - elif T is TVec2[float32]: value.vec2f32[] = data - elif T is TVec2[float64]: value.vec2f64[] = data - elif T is TVec3[float32]: value.vec3f32[] = data - elif T is TVec3[float64]: value.vec3f64[] = data - elif T is TVec4[float32]: value.vec4f32[] = data - elif T is TVec4[float64]: value.vec4f64[] = data - elif T is TMat2[float32]: value.mat2f32[] = data - elif T is TMat2[float64]: value.mat2f64[] = data - elif T is TMat23[float32]: value.mat23f32[] = data - elif T is TMat23[float64]: value.mat23f64[] = data - elif T is TMat32[float32]: value.mat32f32[] = data - elif T is TMat32[float64]: value.mat32f64[] = data - elif T is TMat3[float32]: value.mat3f32[] = data - elif T is TMat3[float64]: value.mat3f64[] = data - elif T is TMat34[float32]: value.mat34f32[] = data - elif T is TMat34[float64]: value.mat34f64[] = data - elif T is TMat43[float32]: value.mat43f32[] = data - elif T is TMat43[float64]: value.mat43f64[] = data - elif T is TMat4[float32]: value.mat4f32[] = data - elif T is TMat4[float64]: value.mat4f64[] = data - elif T is Texture: value.texture[] = data - else: {. error: "Virtual datatype has no values" .} - -proc setValue*[T: GPUType|int|uint|float](value: var DataList, i: int, data: T) = - assert i < value.len - when T is float32: value.float32[i] = data - elif T is float64: value.float64[i] = data - elif T is int8: value.int8[i] = data - elif T is int16: value.int16[i] = data - elif T is int32: value.int32[i] = data - elif T is int64: value.int64[i] = data - elif T is uint8: value.uint8[i] = data - elif T is uint16: value.uint16[i] = data - elif T is uint32: value.uint32[i] = data - elif T is uint64: value.uint64[i] = data - elif T is int and sizeof(int) == sizeof(int32): value.int32[i] = data - elif T is int and sizeof(int) == sizeof(int64): value.int64[i] = data - elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[i] = data - elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[i] = data - elif T is float and sizeof(float) == sizeof(float32): value.float32[i] = data - elif T is float and sizeof(float) == sizeof(float64): value.float64[i] = data - elif T is TVec2[int32]: value.vec2i32[i] = data - elif T is TVec2[int64]: value.vec2i64[i] = data - elif T is TVec3[int32]: value.vec3i32[i] = data - elif T is TVec3[int64]: value.vec3i64[i] = data - elif T is TVec4[int32]: value.vec4i32[i] = data - elif T is TVec4[int64]: value.vec4i64[i] = data - elif T is TVec2[uint32]: value.vec2u32[i] = data - elif T is TVec2[uint64]: value.vec2u64[i] = data - elif T is TVec3[uint32]: value.vec3u32[i] = data - elif T is TVec3[uint64]: value.vec3u64[i] = data - elif T is TVec4[uint32]: value.vec4u32[i] = data - elif T is TVec4[uint64]: value.vec4u64[i] = data - elif T is TVec2[float32]: value.vec2f32[i] = data - elif T is TVec2[float64]: value.vec2f64[i] = data - elif T is TVec3[float32]: value.vec3f32[i] = data - elif T is TVec3[float64]: value.vec3f64[i] = data - elif T is TVec4[float32]: value.vec4f32[i] = data - elif T is TVec4[float64]: value.vec4f64[i] = data - elif T is TMat2[float32]: value.mat2f32[i] = data - elif T is TMat2[float64]: value.mat2f64[i] = data - elif T is TMat23[float32]: value.mat23f32[i] = data - elif T is TMat23[float64]: value.mat23f64[i] = data - elif T is TMat32[float32]: value.mat32f32[i] = data - elif T is TMat32[float64]: value.mat32f64[i] = data - elif T is TMat3[float32]: value.mat3f32[i] = data - elif T is TMat3[float64]: value.mat3f64[i] = data - elif T is TMat34[float32]: value.mat34f32[i] = data - elif T is TMat34[float64]: value.mat34f64[i] = data - elif T is TMat43[float32]: value.mat43f32[i] = data - elif T is TMat43[float64]: value.mat43f64[i] = data - elif T is TMat4[float32]: value.mat4f32[i] = data - elif T is TMat4[float64]: value.mat4f64[i] = data - elif T is Texture: value.texture[i] = data - else: {. error: "Virtual datatype has no values" .} - -proc appendFrom*(a: var DataList, i: int, b: DataList, j: int) = - assert a.theType == b.theType - case a.theType - of Float32: a.float32[i] = b.float32[j] - of Float64: a.float64[i] = b.float64[j] - of Int8: a.int8[i] = b.int8[j] - of Int16: a.int16[i] = b.int16[j] - of Int32: a.int32[i] = b.int32[j] - of Int64: a.int64[i] = b.int64[j] - of UInt8: a.uint8[i] = b.uint8[j] - of UInt16: a.uint16[i] = b.uint16[j] - of UInt32: a.uint32[i] = b.uint32[j] - of UInt64: a.uint64[i] = b.uint64[j] - of Vec2I32: a.vec2i32[i] = b.vec2i32[j] - of Vec2I64: a.vec2i64[i] = b.vec2i64[j] - of Vec3I32: a.vec3i32[i] = b.vec3i32[j] - of Vec3I64: a.vec3i64[i] = b.vec3i64[j] - of Vec4I32: a.vec4i32[i] = b.vec4i32[j] - of Vec4I64: a.vec4i64[i] = b.vec4i64[j] - of Vec2U32: a.vec2u32[i] = b.vec2u32[j] - of Vec2U64: a.vec2u64[i] = b.vec2u64[j] - of Vec3U32: a.vec3u32[i] = b.vec3u32[j] - of Vec3U64: a.vec3u64[i] = b.vec3u64[j] - of Vec4U32: a.vec4u32[i] = b.vec4u32[j] - of Vec4U64: a.vec4u64[i] = b.vec4u64[j] - of Vec2F32: a.vec2f32[i] = b.vec2f32[j] - of Vec2F64: a.vec2f64[i] = b.vec2f64[j] - of Vec3F32: a.vec3f32[i] = b.vec3f32[j] - of Vec3F64: a.vec3f64[i] = b.vec3f64[j] - of Vec4F32: a.vec4f32[i] = b.vec4f32[j] - of Vec4F64: a.vec4f64[i] = b.vec4f64[j] - of Mat2F32: a.mat2f32[i] = b.mat2f32[j] - of Mat2F64: a.mat2f64[i] = b.mat2f64[j] - of Mat23F32: a.mat23f32[i] = b.mat23f32[j] - of Mat23F64: a.mat23f64[i] = b.mat23f64[j] - of Mat32F32: a.mat32f32[i] = b.mat32f32[j] - of Mat32F64: a.mat32f64[i] = b.mat32f64[j] - of Mat3F32: a.mat3f32[i] = b.mat3f32[j] - of Mat3F64: a.mat3f64[i] = b.mat3f64[j] - of Mat34F32: a.mat34f32[i] = b.mat34f32[j] - of Mat34F64: a.mat34f64[i] = b.mat34f64[j] - of Mat43F32: a.mat43f32[i] = b.mat43f32[j] - of Mat43F64: a.mat43f64[i] = b.mat43f64[j] - of Mat4F32: a.mat4f32[i] = b.mat4f32[j] - of Mat4F64: a.mat4f64[i] = b.mat4f64[j] - of TextureType: a.texture[i] = b.texture[j] - -proc copy*(datalist: DataList): DataList = - result = initDataList(datalist.theType) - result.appendValues(datalist) - -func `$`*(list: DataList): string = - case list.theType - of Float32: $list.float32[] - of Float64: $list.float64[] - of Int8: $list.int8[] - of Int16: $list.int16[] - of Int32: $list.int32[] - of Int64: $list.int64[] - of UInt8: $list.uint8[] - of UInt16: $list.uint16[] - of UInt32: $list.uint32[] - of UInt64: $list.uint64[] - of Vec2I32: $list.vec2i32[] - of Vec2I64: $list.vec2i64[] - of Vec3I32: $list.vec3i32[] - of Vec3I64: $list.vec3i64[] - of Vec4I32: $list.vec4i32[] - of Vec4I64: $list.vec4i64[] - of Vec2U32: $list.vec2u32[] - of Vec2U64: $list.vec2u64[] - of Vec3U32: $list.vec3u32[] - of Vec3U64: $list.vec3u64[] - of Vec4U32: $list.vec4u32[] - of Vec4U64: $list.vec4u64[] - of Vec2F32: $list.vec2f32[] - of Vec2F64: $list.vec2f64[] - of Vec3F32: $list.vec3f32[] - of Vec3F64: $list.vec3f64[] - of Vec4F32: $list.vec4f32[] - of Vec4F64: $list.vec4f64[] - of Mat2F32: $list.mat2f32[] - of Mat2F64: $list.mat2f64[] - of Mat23F32: $list.mat23f32[] - of Mat23F64: $list.mat23f64[] - of Mat32F32: $list.mat32f32[] - of Mat32F64: $list.mat32f64[] - of Mat3F32: $list.mat3f32[] - of Mat3F64: $list.mat3f64[] - of Mat34F32: $list.mat34f32[] - of Mat34F64: $list.mat34f64[] - of Mat43F32: $list.mat43f32[] - of Mat43F64: $list.mat43f64[] - of Mat4F32: $list.mat4f32[] - of Mat4F64: $list.mat4f64[] - of TextureType: $list.texture[] diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/fonttypes.nim --- a/src/semicongine/core/fonttypes.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -import std/tables -import std/unicode - -import ./vulkanapi -import ./imagetypes -import ./vector - -var FONTSAMPLER_SOFT* = Sampler( - magnification: VK_FILTER_LINEAR, - minification: VK_FILTER_LINEAR, - wrapModeS: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - wrapModeT: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - ) -var FONTSAMPLER_HARD* = Sampler( - magnification: VK_FILTER_NEAREST, - minification: VK_FILTER_NEAREST, - wrapModeS: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - wrapModeT: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - ) - - -type - GlyphInfo* = object - uvs*: array[4, Vec2f] - dimension*: Vec2f - topOffset*: float32 - leftOffset*: float32 - advance*: float32 - Font* = object - name*: string # used to reference fontAtlas will be referenced in shader - glyphs*: Table[Rune, GlyphInfo] - fontAtlas*: Texture - maxHeight*: int - kerning*: Table[(Rune, Rune), float32] - resolution*: float32 - fontscale*: float32 diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/gpu_types.nim --- a/src/semicongine/core/gpu_types.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,400 +0,0 @@ -import std/strformat -import std/tables - -import ./vulkanapi -import ./vector -import ./matrix -import ./imagetypes - -type - GPUType* = float32 | float64 | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | TVec2[int32] | TVec2[int64] | TVec3[int32] | TVec3[int64] | TVec4[int32] | TVec4[int64] | TVec2[uint32] | TVec2[uint64] | TVec3[uint32] | TVec3[uint64] | TVec4[uint32] | TVec4[uint64] | TVec2[float32] | TVec2[float64] | TVec3[float32] | TVec3[float64] | TVec4[float32] | TVec4[float64] | TMat2[float32] | TMat2[float64] | TMat23[float32] | TMat23[float64] | TMat32[float32] | TMat32[float64] | TMat3[float32] | TMat3[float64] | TMat34[float32] | TMat34[float64] | TMat43[float32] | TMat43[float64] | TMat4[float32] | TMat4[float64] | Texture - DataType* = enum - Float32 - Float64 - Int8 - Int16 - Int32 - Int64 - UInt8 - UInt16 - UInt32 - UInt64 - Vec2I32 - Vec2I64 - Vec3I32 - Vec3I64 - Vec4I32 - Vec4I64 - Vec2U32 - Vec2U64 - Vec3U32 - Vec3U64 - Vec4U32 - Vec4U64 - Vec2F32 - Vec2F64 - Vec3F32 - Vec3F64 - Vec4F32 - Vec4F64 - Mat2F32 - Mat2F64 - Mat23F32 - Mat23F64 - Mat32F32 - Mat32F64 - Mat3F32 - Mat3F64 - Mat34F32 - Mat34F64 - Mat43F32 - Mat43F64 - Mat4F32 - Mat4F64 - TextureType - MemoryPerformanceHint* = enum - PreferFastRead, PreferFastWrite - ShaderAttribute* = object - name*: string - theType*: DataType - arrayCount*: int - perInstance*: bool - noInterpolation: bool - memoryPerformanceHint*: MemoryPerformanceHint - -func vertexInputs*(attributes: seq[ShaderAttribute]): seq[ShaderAttribute] = - for attr in attributes: - if attr.perInstance == false: - result.add attr - -func instanceInputs*(attributes: seq[ShaderAttribute]): seq[ShaderAttribute] = - for attr in attributes: - if attr.perInstance == false: - result.add attr - -func numberOfVertexInputAttributeDescriptors*(theType: DataType): int = - case theType: - of Mat2F32, Mat2F64, Mat23F32, Mat23F64: 2 - of Mat32F32, Mat32F64, Mat3F32, Mat3F64, Mat34F32, Mat34F64: 3 - of Mat43F32, Mat43F64, Mat4F32, Mat4F64: 4 - else: 1 - -func size*(theType: DataType): int = - case theType: - of Float32: 4 - of Float64: 8 - of Int8: 1 - of Int16: 2 - of Int32: 4 - of Int64: 8 - of UInt8: 1 - of UInt16: 2 - of UInt32: 4 - of UInt64: 8 - of Vec2I32: 8 - of Vec2I64: 16 - of Vec3I32: 12 - of Vec3I64: 24 - of Vec4I32: 16 - of Vec4I64: 32 - of Vec2U32: 8 - of Vec2U64: 16 - of Vec3U32: 12 - of Vec3U64: 24 - of Vec4U32: 16 - of Vec4U64: 32 - of Vec2F32: 8 - of Vec2F64: 16 - of Vec3F32: 12 - of Vec3F64: 24 - of Vec4F32: 16 - of Vec4F64: 32 - of Mat2F32: 16 - of Mat2F64: 32 - of Mat23F32: 24 - of Mat23F64: 48 - of Mat32F32: 24 - of Mat32F64: 48 - of Mat3F32: 36 - of Mat3F64: 72 - of Mat34F32: 48 - of Mat34F64: 92 - of Mat43F32: 48 - of Mat43F64: 92 - of Mat4F32: 64 - of Mat4F64: 128 - of TextureType: 0 - -func size*(attribute: ShaderAttribute, perDescriptor=false): int = - if perDescriptor: - attribute.theType.size div attribute.theType.numberOfVertexInputAttributeDescriptors - else: - if attribute.arrayCount == 0: - attribute.theType.size - else: - attribute.theType.size * attribute.arrayCount - -func size*(theType: seq[ShaderAttribute]): int = - for attribute in theType: - result += attribute.size - -func getDataType*[T: GPUType|int|uint|float](): DataType = - when T is float32: Float32 - elif T is float64: Float64 - elif T is int8: Int8 - elif T is int16: Int16 - elif T is int32: Int32 - elif T is int64: Int64 - elif T is uint8: UInt8 - elif T is uint16: UInt16 - elif T is uint32: UInt32 - elif T is uint64: UInt64 - elif T is int and sizeof(int) == sizeof(int64): Int64 - elif T is int and sizeof(int) == sizeof(int32): Int32 - elif T is uint and sizeof(uint) == sizeof(uint64): UInt64 - elif T is uint and sizeof(uint) == sizeof(uint32): UInt32 - elif T is float and sizeof(float) == sizeof(float32): Float32 - elif T is float and sizeof(float) == sizeof(float64): Float64 - elif T is TVec2[int32]: Vec2I32 - elif T is TVec2[int64]: Vec2I64 - elif T is TVec3[int32]: Vec3I32 - elif T is TVec3[int64]: Vec3I64 - elif T is TVec4[int32]: Vec4I32 - elif T is TVec4[int64]: Vec4I64 - elif T is TVec2[uint32]: Vec2U32 - elif T is TVec2[uint64]: Vec2U64 - elif T is TVec3[uint32]: Vec3U32 - elif T is TVec3[uint64]: Vec3U64 - elif T is TVec4[uint32]: Vec4U32 - elif T is TVec4[uint64]: Vec4U64 - elif T is TVec2[float32]: Vec2F32 - elif T is TVec2[float64]: Vec2F64 - elif T is TVec3[float32]: Vec3F32 - elif T is TVec3[float64]: Vec3F64 - elif T is TVec4[float32]: Vec4F32 - elif T is TVec4[float64]: Vec4F64 - elif T is TMat2[float32]: Mat2F32 - elif T is TMat2[float64]: Mat2F64 - elif T is TMat23[float32]: Mat23F32 - elif T is TMat23[float64]: Mat23F64 - elif T is TMat32[float32]: Mat32F32 - elif T is TMat32[float64]: Mat32F64 - elif T is TMat3[float32]: Mat3F32 - elif T is TMat3[float64]: Mat3F64 - elif T is TMat34[float32]: Mat34F32 - elif T is TMat34[float64]: Mat34F64 - elif T is TMat43[float32]: Mat43F32 - elif T is TMat43[float64]: Mat43F64 - elif T is TMat4[float32]: Mat4F32 - elif T is TMat4[float64]: Mat4F64 - elif T is Texture: TextureType - else: - static: - raise newException(Exception, &"Unsupported data type for GPU data: {name(T)}" ) - -func attr*[T: GPUType]( - name: string, - perInstance=false, - arrayCount=0, - noInterpolation=false, - memoryPerformanceHint=PreferFastRead, -): auto = - ShaderAttribute( - name: name, - theType: getDataType[T](), - perInstance: perInstance, - arrayCount: arrayCount, - noInterpolation: noInterpolation, - memoryPerformanceHint: memoryPerformanceHint, - ) - -const TYPEMAP = { - Float32: VK_FORMAT_R32_SFLOAT, - Float64: VK_FORMAT_R64_SFLOAT, - Int8: VK_FORMAT_R8_SINT, - Int16: VK_FORMAT_R16_SINT, - Int32: VK_FORMAT_R32_SINT, - Int64: VK_FORMAT_R64_SINT, - UInt8: VK_FORMAT_R8_UINT, - UInt16: VK_FORMAT_R16_UINT, - UInt32: VK_FORMAT_R32_UINT, - UInt64: VK_FORMAT_R64_UINT, - Vec2I32: VK_FORMAT_R32G32_SINT, - Vec2I64: VK_FORMAT_R64G64_SINT, - Vec3I32: VK_FORMAT_R32G32B32_SINT, - Vec3I64: VK_FORMAT_R64G64B64_SINT, - Vec4I32: VK_FORMAT_R32G32B32A32_SINT, - Vec4I64: VK_FORMAT_R64G64B64A64_SINT, - Vec2U32: VK_FORMAT_R32G32_UINT, - Vec2U64: VK_FORMAT_R64G64_UINT, - Vec3U32: VK_FORMAT_R32G32B32_UINT, - Vec3U64: VK_FORMAT_R64G64B64_UINT, - Vec4U32: VK_FORMAT_R32G32B32A32_UINT, - Vec4U64: VK_FORMAT_R64G64B64A64_UINT, - Vec2F32: VK_FORMAT_R32G32_SFLOAT, - Vec2F64: VK_FORMAT_R64G64_SFLOAT, - Vec3F32: VK_FORMAT_R32G32B32_SFLOAT, - Vec3F64: VK_FORMAT_R64G64B64_SFLOAT, - Vec4F32: VK_FORMAT_R32G32B32A32_SFLOAT, - Vec4F64: VK_FORMAT_R64G64B64A64_SFLOAT, - Mat2F32: VK_FORMAT_R32G32_SFLOAT, - Mat2F64: VK_FORMAT_R64G64_SFLOAT, - Mat23F32: VK_FORMAT_R32G32B32_SFLOAT, - Mat23F64: VK_FORMAT_R64G64B64_SFLOAT, - Mat32F32: VK_FORMAT_R32G32_SFLOAT, - Mat32F64: VK_FORMAT_R64G64_SFLOAT, - Mat3F32: VK_FORMAT_R32G32B32_SFLOAT, - Mat3F64: VK_FORMAT_R64G64B64_SFLOAT, - Mat34F32: VK_FORMAT_R32G32B32A32_SFLOAT, - Mat34F64: VK_FORMAT_R64G64B64A64_SFLOAT, - Mat43F32: VK_FORMAT_R32G32B32_SFLOAT, - Mat43F64: VK_FORMAT_R64G64B64_SFLOAT, - Mat4F32: VK_FORMAT_R32G32B32A32_SFLOAT, - Mat4F64: VK_FORMAT_R64G64B64A64_SFLOAT, -}.toTable - -func getVkFormat*(theType: DataType): VkFormat = - TYPEMAP[theType] - -# from https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html -func nLocationSlots*(theType: DataType): int = - #[ - single location: - 16-bit scalar and vector types, and - 32-bit scalar and vector types, and - 64-bit scalar and 2-component vector types. - two locations - 64-bit three- and four-component vectors - ]# - case theType: - of Float32: 1 - of Float64: 1 - of Int8: 1 - of Int16: 1 - of Int32: 1 - of Int64: 1 - of UInt8: 1 - of UInt16: 1 - of UInt32: 1 - of UInt64: 1 - of Vec2I32: 1 - of Vec2I64: 1 - of Vec3I32: 1 - of Vec3I64: 2 - of Vec4I32: 1 - of Vec4I64: 2 - of Vec2U32: 1 - of Vec2U64: 1 - of Vec3U32: 1 - of Vec3U64: 2 - of Vec4U32: 1 - of Vec4U64: 2 - of Vec2F32: 1 - of Vec2F64: 1 - of Vec3F32: 1 - of Vec3F64: 2 - of Vec4F32: 1 - of Vec4F64: 2 - of Mat2F32: 1 - of Mat2F64: 1 - of Mat23F32: 1 - of Mat23F64: 2 - of Mat32F32: 1 - of Mat32F64: 1 - of Mat3F32: 1 - of Mat3F64: 2 - of Mat34F32: 1 - of Mat34F64: 2 - of Mat43F32: 1 - of Mat43F64: 2 - of Mat4F32: 1 - of Mat4F64: 2 - of TextureType: 1 - -func glslType*(theType: DataType): string = - # todo: likely not correct as we would need to enable some - # extensions somewhere (Vulkan/GLSL compiler?) to have - # everything work as intended. Or maybe the GPU driver does - # some automagic conversion stuf.. - case theType: - of Float32: "float" - of Float64: "double" - of Int8, Int16, Int32, Int64: "int" - of UInt8, UInt16, UInt32, UInt64: "uint" - of Vec2I32: "ivec2" - of Vec2I64: "ivec2" - of Vec3I32: "ivec3" - of Vec3I64: "ivec3" - of Vec4I32: "ivec4" - of Vec4I64: "ivec4" - of Vec2U32: "uvec2" - of Vec2U64: "uvec2" - of Vec3U32: "uvec3" - of Vec3U64: "uvec3" - of Vec4U32: "uvec4" - of Vec4U64: "uvec4" - of Vec2F32: "vec2" - of Vec2F64: "dvec2" - of Vec3F32: "vec3" - of Vec3F64: "dvec3" - of Vec4F32: "vec4" - of Vec4F64: "dvec4" - of Mat2F32: "mat2" - of Mat2F64: "dmat2" - of Mat23F32: "mat23" - of Mat23F64: "dmat23" - of Mat32F32: "mat32" - of Mat32F64: "dmat32" - of Mat3F32: "mat3" - of Mat3F64: "dmat3" - of Mat34F32: "mat34" - of Mat34F64: "dmat34" - of Mat43F32: "mat43" - of Mat43F64: "dmat43" - of Mat4F32: "mat4" - of Mat4F64: "dmat4" - of TextureType: "sampler2D" - -func glslInput*(group: openArray[ShaderAttribute]): seq[string] = - if group.len == 0: - return @[] - var i = 0 - for attribute in group: - assert attribute.arrayCount == 0, "arrays not supported for shader vertex attributes" - let flat = if attribute.noInterpolation: "flat " else: "" - result.add &"layout(location = {i}) {flat}in {attribute.theType.glslType} {attribute.name};" - for j in 0 ..< attribute.theType.numberOfVertexInputAttributeDescriptors: - i += attribute.theType.nLocationSlots - -func glslUniforms*(group: openArray[ShaderAttribute], blockName="Uniforms", binding: int): seq[string] = - if group.len == 0: - return @[] - # currently only a single uniform block supported, therefore binding = 0 - result.add(&"layout(std430, binding = {binding}) uniform T{blockName} {{") - for attribute in group: - var arrayDecl = "" - if attribute.arrayCount > 0: - arrayDecl = &"[{attribute.arrayCount}]" - result.add(&" {attribute.theType.glslType} {attribute.name}{arrayDecl};") - result.add(&"}} {blockName};") - -func glslSamplers*(group: openArray[ShaderAttribute], basebinding: int): seq[string] = - if group.len == 0: - return @[] - var thebinding = basebinding - for attribute in group: - var arrayDecl = "" - if attribute.arrayCount > 0: - arrayDecl = &"[{attribute.arrayCount}]" - result.add(&"layout(binding = {thebinding}) uniform {attribute.theType.glslType} {attribute.name}{arrayDecl};") - inc thebinding - -func glslOutput*(group: openArray[ShaderAttribute]): seq[string] = - if group.len == 0: - return @[] - var i = 0 - for attribute in group: - assert attribute.arrayCount == 0, "arrays not supported for outputs" - let flat = if attribute.noInterpolation: "flat " else: "" - result.add &"layout(location = {i}) {flat}out {attribute.theType.glslType} {attribute.name};" - i += 1 diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/imagetypes.nim --- a/src/semicongine/core/imagetypes.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -import std/strformat - -import ./vulkanapi -import ./vector - -type - Pixel* = array[4, uint8] - ImageObject* = object - width*: int - height*: int - imagedata*: seq[Pixel] - Sampler* = object - magnification*: VkFilter = VK_FILTER_LINEAR - minification*: VkFilter = VK_FILTER_LINEAR - wrapModeS*: VkSamplerAddressMode = VK_SAMPLER_ADDRESS_MODE_REPEAT - wrapModeT*: VkSamplerAddressMode = VK_SAMPLER_ADDRESS_MODE_REPEAT - - Image* = ref ImageObject - Texture* = object - name*: string - image*: Image - sampler*: Sampler - -converter toRGBA*(p: Pixel): Vec4f = - newVec4f(float32(p[0]) / 255'f32, float32(p[1]) / 255'f32, float32(p[2]) / 255'f32, float32(p[3]) / 255'f32) - -proc `$`*(image: Image): string = - &"{image.width}x{image.height}" - -proc `$`*(texture: Texture): string = - &"{texture.name} {texture.image}" - -proc `[]`*(image: Image, x, y: int): Pixel = - assert x < image.width - assert y < image.height - - image[].imagedata[y * image.width + x] - -proc `[]=`*(image: var Image, x, y: int, value: Pixel) = - assert x < image.width - assert y < image.height - - image[].imagedata[y * image.width + x] = value - -const EMPTYPIXEL = [0'u8, 0'u8, 0'u8, 0'u8] -proc newImage*(width, height: int, imagedata: seq[Pixel] = @[], fill=EMPTYPIXEL): Image = - assert width > 0 and height > 0 - assert imagedata.len == width * height or imagedata.len == 0 - - result = new Image - result.imagedata = (if imagedata.len == 0: newSeq[Pixel](width * height) else: imagedata) - assert width * height == result.imagedata.len - - result.width = width - result.height = height - if fill != EMPTYPIXEL: - for y in 0 ..< height: - for x in 0 ..< width: - result[x, y] = fill - -let INVALID_TEXTURE* = Texture(name: "Invalid texture", image: newImage(1, 1, @[[255'u8, 0'u8, 255'u8, 255'u8]]), sampler: Sampler( - magnification: VK_FILTER_NEAREST, - minification: VK_FILTER_NEAREST, - wrapModeS: VK_SAMPLER_ADDRESS_MODE_REPEAT, - wrapModeT: VK_SAMPLER_ADDRESS_MODE_REPEAT, - ) -) -let EMPTY_TEXTURE* = Texture(name: "Empty texture", image: newImage(1, 1, @[[255'u8, 255'u8, 255'u8, 255'u8]]), sampler: Sampler( - magnification: VK_FILTER_NEAREST, - minification: VK_FILTER_NEAREST, - wrapModeS: VK_SAMPLER_ADDRESS_MODE_REPEAT, - wrapModeT: VK_SAMPLER_ADDRESS_MODE_REPEAT, - ) -) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/matrix.nim --- a/src/semicongine/core/matrix.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,477 +0,0 @@ -import std/math -import std/macros -import std/random -import std/strutils -import std/strformat -import std/typetraits - -import ./vector - -export math - -type - # layout is row-first - # having an object instead of directly aliasing the array seems a bit ugly at - # first, but is necessary to be able to work correctly with distinguished - # types (i.e. TMat23 and TMat32 would be an alias for the same type array[6, T] - # which prevents the type system from identifying the correct type at times) - # - # Though, great news is that objects have zero overhead! - TMat2*[T: SomeNumber] = object - data*: array[4, T] - TMat23*[T: SomeNumber] = object - data*: array[6, T] - TMat32*[T: SomeNumber] = object - data*: array[6, T] - TMat3*[T: SomeNumber] = object - data*: array[9, T] - TMat34*[T: SomeNumber] = object - data*: array[12, T] - TMat43*[T: SomeNumber] = object - data*: array[12, T] - TMat4*[T: SomeNumber] = object - data*: array[16, T] - TMat* = TMat2|TMat3|TMat4|TMat23|TMat32|TMat34|TMat43 - Mat2* = TMat2[float32] - Mat23* = TMat23[float32] - Mat32* = TMat32[float32] - Mat3* = TMat3[float32] - Mat34* = TMat34[float32] - Mat43* = TMat43[float32] - Mat4* = TMat4[float32] - -func unit2[T: SomeNumber](): auto {.compiletime.} = TMat2[T](data:[ - T(1), T(0), - T(0), T(1), -]) -func unit3[T: SomeNumber](): auto {.compiletime.} = TMat3[T](data:[ - T(1), T(0), T(0), - T(0), T(1), T(0), - T(0), T(0), T(1), -]) -func unit4[T: SomeNumber](): auto {.compiletime.} = TMat4[T](data: [ - T(1), T(0), T(0), T(0), - T(0), T(1), T(0), T(0), - T(0), T(0), T(1), T(0), - T(0), T(0), T(0), T(1), -]) - -# generates constants: Unit -# Also for Y, Z, R, G, B -# not sure if this is necessary or even a good idea... -macro generateAllConsts() = - result = newStmtList() - for theType in ["int", "int8", "int16", "int32", "int64", "float", "float32", "float64"]: - var typename = theType[0 .. 0] - if theType[^2].isDigit: - typename = typename & theType[^2] - if theType[^1].isDigit: - typename = typename & theType[^1] - result.add(newConstStmt( - postfix(ident("Unit2" & typename), "*"), - newCall(nnkBracketExpr.newTree(ident("unit2"), ident(theType))) - )) - result.add(newConstStmt( - postfix(ident("Unit3" & typename), "*"), - newCall(nnkBracketExpr.newTree(ident("unit3"), ident(theType))) - )) - result.add(newConstStmt( - postfix(ident("Unit4" & typename), "*"), - newCall(nnkBracketExpr.newTree(ident("unit4"), ident(theType))) - )) - -generateAllConsts() - -const Unit2* = unit2[float32]() -const Unit3* = unit3[float32]() -const Unit4* = unit4[float32]() - -template rowCount*(m: typedesc): int = - when m is TMat2: 2 - elif m is TMat23: 2 - elif m is TMat32: 3 - elif m is TMat3: 3 - elif m is TMat34: 3 - elif m is TMat43: 4 - elif m is TMat4: 4 -template columnCount*(m: typedesc): int = - when m is TMat2: 2 - elif m is TMat23: 3 - elif m is TMat32: 2 - elif m is TMat3: 3 - elif m is TMat34: 4 - elif m is TMat43: 3 - elif m is TMat4: 4 -template matlen*(m: typedesc): int = - when m is TMat2: 4 - elif m is TMat23: 6 - elif m is TMat32: 6 - elif m is TMat3: 9 - elif m is TMat34: 12 - elif m is TMat43: 12 - elif m is TMat4: 16 - - -func toString[T](value: T): string = - var - strvalues: seq[string] - maxwidth = 0 - - for n in value.data: - let strval = &"{n:.2}" - strvalues.add(strval) - if strval.len > maxwidth: - maxwidth = strval.len - - for i in 0 ..< strvalues.len: - let filler = " ".repeat(maxwidth - strvalues[i].len) - if i mod T.columnCount == T.columnCount - 1: - result &= filler & strvalues[i] & "\n" - else: - if i mod T.columnCount == 0: - result &= " " - result &= filler & strvalues[i] & " " - result = $T & "\n" & result - -func `$`*(v: TMat2[SomeNumber]): string = toString[TMat2[SomeNumber]](v) -func `$`*(v: TMat23[SomeNumber]): string = toString[TMat23[SomeNumber]](v) -func `$`*(v: TMat32[SomeNumber]): string = toString[TMat32[SomeNumber]](v) -func `$`*(v: TMat3[SomeNumber]): string = toString[TMat3[SomeNumber]](v) -func `$`*(v: TMat34[SomeNumber]): string = toString[TMat34[SomeNumber]](v) -func `$`*(v: TMat43[SomeNumber]): string = toString[TMat43[SomeNumber]](v) -func `$`*(v: TMat4[SomeNumber]): string = toString[TMat4[SomeNumber]](v) - -func `[]`*[T: TMat](m: T, row, col: int): auto = m.data[col + row * T.columnCount] -func `[]=`*[T: TMat, U](m: var T, row, col: int, value: U) = m.data[col + row * T.columnCount] = value -func `[]`*[T: TMat](m: T, i: int): auto = m.data[i] -func `[]=`*[T: TMat, U](m: var T, i: int, value: U) = m.data[i] = value - -func row*[T: TMat2](m: T, i: 0..1): auto = TVec2([m[i, 0], m[i, 1]]) -func row*[T: TMat32](m: T, i: 0..2): auto = TVec2([m[i, 0], m[i, 1]]) -func row*[T: TMat23](m: T, i: 0..1): auto = TVec3([m[i, 0], m[i, 1], m[i, 2]]) -func row*[T: TMat3](m: T, i: 0..2): auto = TVec3([m[i, 0], m[i, 1], m[i, 2]]) -func row*[T: TMat43](m: T, i: 0..3): auto = TVec3([m[i, 0], m[i, 1], m[i, 2]]) -func row*[T: TMat34](m: T, i: 0..2): auto = TVec4([m[i, 0], m[i, 1], m[i, 2], m[i, 3]]) -func row*[T: TMat4](m: T, i: 0..3): auto = TVec4([m[i, 0], m[i, 1], m[i, 2], m[i, 3]]) - -func col*[T: TMat2](m: T, i: 0..1): auto = TVec2([m[0, i], m[1, i]]) -func col*[T: TMat23](m: T, i: 0..2): auto = TVec2([m[0, i], m[1, i]]) -func col*[T: TMat32](m: T, i: 0..1): auto = TVec3([m[0, i], m[1, i], m[2, i]]) -func col*[T: TMat3](m: T, i: 0..2): auto = TVec3([m[0, i], m[1, i], m[2, i]]) -func col*[T: TMat34](m: T, i: 0..3): auto = TVec3([m[0, i], m[1, i], m[2, i]]) -func col*[T: TMat43](m: T, i: 0..2): auto = TVec4([m[0, i], m[1, i], m[2, i], m[3, i]]) -func col*[T: TMat4](m: T, i: 0..3): auto = TVec4([m[0, i], m[1, i], m[2, i], m[3, i]]) - -proc createMatMatMultiplicationOperator(leftType: typedesc, rightType: typedesc, outType: typedesc): NimNode = - var data = nnkBracket.newTree() - for i in 0 ..< rowCount(leftType): - for j in 0 ..< rightType.columnCount: - data.add(newCall( - ident("sum"), - infix( - newCall(newDotExpr(ident("a"), ident("row")), newLit(i)), - "*", - newCall(newDotExpr(ident("b"), ident("col")), newLit(j)) - ) - )) - - return newProc( - postfix(nnkAccQuoted.newTree(ident("*")), "*"), - params=[ - ident("auto"), - newIdentDefs(ident("a"), ident(leftType.name)), - newIdentDefs(ident("b"), ident(rightType.name)) - ], - body=nnkObjConstr.newTree(ident(outType.name), nnkExprColonExpr.newTree(ident("data"), data)), - procType=nnkFuncDef, - ) - -proc createMatMatAdditionOperator(theType: typedesc): NimNode = - var data = nnkBracket.newTree() - for i in 0 ..< matlen(theType): - data.add( - infix( - nnkBracketExpr.newTree(ident("a"), newLit(i)), - "+", - nnkBracketExpr.newTree(ident("b"), newLit(i)), - )) - - return newProc( - postfix(nnkAccQuoted.newTree(ident("+")), "*"), - params=[ - ident("auto"), - newIdentDefs(ident("a"), ident(theType.name)), - newIdentDefs(ident("b"), ident(theType.name)) - ], - body=nnkObjConstr.newTree(ident(theType.name), nnkExprColonExpr.newTree(ident("data"), data)), - procType=nnkFuncDef, - ) - -proc createVecMatMultiplicationOperator(matType: typedesc, vecType: typedesc): NimNode = - var data = nnkBracket.newTree() - for i in 0 ..< matType.rowCount: - data.add(newCall( - ident("sum"), - infix( - ident("v"), - "*", - newCall(newDotExpr(ident("m"), ident("row")), newLit(i)) - ) - )) - - let resultVec = newCall( - nnkBracketExpr.newTree(ident(vecType.name), ident("T")), - data, - ) - let name = postfix(nnkAccQuoted.newTree(ident("*")), "*") - let genericParams = nnkGenericParams.newTree(nnkIdentDefs.newTree(ident("T"), ident("SomeNumber"), newEmptyNode())) - let formalParams = nnkFormalParams.newTree( - ident("auto"), - newIdentDefs(ident("m"), nnkBracketExpr.newTree(ident(matType.name), ident("T"))), - newIdentDefs(ident("v"), nnkBracketExpr.newTree(ident(vecType.name), ident("T"))), - ) - - return nnkFuncDef.newTree( - name, - newEmptyNode(), - genericParams, - formalParams, - newEmptyNode(), - newEmptyNode(), - resultVec - ) - - -proc createMatScalarOperator(matType: typedesc, op: string): NimNode = - result = newStmtList() - - var data = nnkBracket.newTree() - for i in 0 ..< matType.rowCount * matType.columnCount: - data.add(infix(nnkBracketExpr.newTree(newDotExpr(ident("a"), ident("data")), newLit(i)), op, ident("b"))) - result.add(newProc( - postfix(nnkAccQuoted.newTree(ident(op)), "*"), - params=[ - ident("auto"), - newIdentDefs(ident("a"), ident(matType.name)), - newIdentDefs(ident("b"), ident("SomeNumber")), - ], - body=nnkObjConstr.newTree(ident(matType.name), nnkExprColonExpr.newTree(ident("data"), data)), - procType=nnkFuncDef, - )) - result.add(newProc( - postfix(nnkAccQuoted.newTree(ident(op)), "*"), - params=[ - ident("auto"), - newIdentDefs(ident("b"), ident("SomeNumber")), - newIdentDefs(ident("a"), ident(matType.name)), - ], - body=nnkObjConstr.newTree(ident(matType.name), nnkExprColonExpr.newTree(ident("data"), data)), - procType=nnkFuncDef, - )) - if op == "-": - var data2 = nnkBracket.newTree() - for i in 0 ..< matType.rowCount * matType.columnCount: - data2.add(prefix(nnkBracketExpr.newTree(newDotExpr(ident("a"), ident("data")), newLit(i)), op)) - result.add(newProc( - postfix(nnkAccQuoted.newTree(ident(op)), "*"), - params=[ - ident("auto"), - newIdentDefs(ident("a"), ident(matType.name)), - ], - body=nnkObjConstr.newTree(ident(matType.name), nnkExprColonExpr.newTree(ident("data"), data2)), - procType=nnkFuncDef, - )) - -macro createAllMultiplicationOperators() = - result = newStmtList() - - for op in ["+", "-", "*", "/"]: - result.add(createMatScalarOperator(TMat2, op)) - result.add(createMatScalarOperator(TMat23, op)) - result.add(createMatScalarOperator(TMat32, op)) - result.add(createMatScalarOperator(TMat3, op)) - result.add(createMatScalarOperator(TMat34, op)) - result.add(createMatScalarOperator(TMat43, op)) - result.add(createMatScalarOperator(TMat4, op)) - - result.add(createMatMatMultiplicationOperator(TMat2, TMat2, TMat2)) - result.add(createMatMatMultiplicationOperator(TMat2, TMat23, TMat23)) - result.add(createMatMatMultiplicationOperator(TMat23, TMat32, TMat2)) - result.add(createMatMatMultiplicationOperator(TMat23, TMat3, TMat23)) - result.add(createMatMatMultiplicationOperator(TMat32, TMat2, TMat32)) - result.add(createMatMatMultiplicationOperator(TMat32, TMat23, TMat3)) - result.add(createMatMatMultiplicationOperator(TMat3, TMat32, TMat32)) - result.add(createMatMatMultiplicationOperator(TMat3, TMat3, TMat3)) - result.add(createMatMatMultiplicationOperator(TMat3, TMat34, TMat34)) - result.add(createMatMatMultiplicationOperator(TMat43, TMat3, TMat43)) - result.add(createMatMatMultiplicationOperator(TMat43, TMat34, TMat4)) - result.add(createMatMatMultiplicationOperator(TMat4, TMat43, TMat43)) - result.add(createMatMatMultiplicationOperator(TMat4, TMat4, TMat4)) - - result.add(createMatMatAdditionOperator(TMat2)) - result.add(createMatMatAdditionOperator(TMat23)) - result.add(createMatMatAdditionOperator(TMat32)) - result.add(createMatMatAdditionOperator(TMat3)) - result.add(createMatMatAdditionOperator(TMat34)) - result.add(createMatMatAdditionOperator(TMat43)) - result.add(createMatMatAdditionOperator(TMat4)) - - result.add(createVecMatMultiplicationOperator(TMat2, TVec2)) - result.add(createVecMatMultiplicationOperator(TMat3, TVec3)) - result.add(createVecMatMultiplicationOperator(TMat4, TVec4)) - -createAllMultiplicationOperators() - -func `*`*(mat: Mat4, vec: Vec3f): Vec3f = - (mat * vec.toVec4(1)).toVec3 - -func transposed*[T](m: TMat2[T]): TMat2[T] = TMat2[T](data: [ - m[0, 0], m[1, 0], - m[0, 1], m[1, 1], -]) -func transposed*[T](m: TMat23[T]): TMat32[T] = TMat32[T](data: [ - m[0, 0], m[1, 0], - m[0, 1], m[1, 1], - m[0, 2], m[1, 2], -]) -func transposed*[T](m: TMat32[T]): TMat23[T] = TMat23[T](data: [ - m[0, 0], m[1, 0], m[2, 0], - m[0, 1], m[1, 1], m[2, 1], -]) -func transposed*[T](m: TMat3[T]): TMat3[T] = TMat3[T](data: [ - m[0, 0], m[1, 0], m[2, 0], - m[0, 1], m[1, 1], m[2, 1], - m[0, 2], m[1, 2], m[2, 2], -]) -func transposed*[T](m: TMat43[T]): TMat34[T] = TMat34[T](data: [ - m[0, 0], m[1, 0], m[2, 0], m[3, 0], - m[0, 1], m[1, 1], m[2, 1], m[3, 1], - m[0, 2], m[1, 2], m[2, 2], m[3, 2], -]) -func transposed*[T](m: TMat34[T]): TMat43[T] = TMat43[T](data: [ - m[0, 0], m[1, 0], m[2, 0], - m[0, 1], m[1, 1], m[2, 1], - m[0, 2], m[1, 2], m[2, 2], - m[0, 3], m[1, 3], m[2, 3], -]) -func transposed*[T](m: TMat4[T]): TMat4[T] = TMat4[T](data: [ - m[0, 0], m[1, 0], m[2, 0], m[3, 0], - m[0, 1], m[1, 1], m[2, 1], m[3, 1], - m[0, 2], m[1, 2], m[2, 2], m[3, 2], - m[0, 3], m[1, 3], m[2, 3], m[3, 3], -]) - -func translate2d*[T](x, y: T): TMat3[T] = TMat3[T](data: [ - T(1), T(0), x, - T(0), T(1), y, - T(0), T(0), T(1), -]) -func scale2d*[T](sx, sy: T): TMat3[T] = TMat3[T](data: [ - sx, T(0), T(0), - T(0), sy, T(0), - T(0), T(0), T(1), -]) -func rotate2d*[T](angle: T): TMat3[T] = TMat3[T](data: [ - cos(angle), -sin(angle), T(0), - sin(angle), cos(angle), T(0), - T(0), T(0), T(1), -]) -func translate*(x=0'f32, y=0'f32, z=0'f32): TMat4[float32] = Mat4(data: [ - 1'f32, 0'f32, 0'f32, x, - 0'f32, 1'f32, 0'f32, y, - 0'f32, 0'f32, 1'f32, z, - 0'f32, 0'f32, 0'f32, 1'f32, -]) -func translate*[T: TVec3](v: T): TMat4[float32] = translate(v[0], v[1], v[2]) -func scale*(x=1'f32, y=1'f32, z=1'f32): Mat4 = Mat4(data: [ - x, 0'f32, 0'f32, 0'f32, - 0'f32, y, 0'f32, 0'f32, - 0'f32, 0'f32, z, 0'f32, - 0'f32, 0'f32, 0'f32, 1'f32, -]) -func scale*[T: TVec3](v: T): TMat4[float32] = scale(v[0], v[1], v[2]) -func rotate*(angle: float32, a: Vec3f): Mat4 = - let - cosa = cos(angle) - sina = sin(angle) - x = a[0] - y = a[1] - z = a[2] - Mat4(data: [ - x * x * (1 - cosa) + cosa, y * x * (1 - cosa) - z * sina, z * x * (1 - cosa) + y * sina, 0'f32, - x * y * (1 - cosa) + z * sina, y * y * (1 - cosa) + cosa, z * y * (1 - cosa) - x * sina, 0'f32, - x * z * (1 - cosa) - y * sina, y * z * (1 - cosa) + x * sina, z * z * (1 - cosa) + cosa, 0'f32, - 0'f32, 0'f32, 0'f32, 1'f32, - ]) - -func asMat3(m: Mat4): auto = - Mat3(data: [ - m[0, 0], m[0, 1], m[0, 2], - m[1, 0], m[1, 1], m[1, 2], - m[2, 0], m[2, 1], m[2, 2], - ]) - - -func inversed*(m: Mat4): Mat4 = - var m3 = m.asMat3.transposed - m3[0, 0] = 1'f32 / m3[0, 0] - m3[1, 1] = 1'f32 / m3[1, 1] - m3[2, 2] = 1'f32 / m3[2, 2] - let col3 = -(m3 * m.col(3).xyz) - return Mat4(data: [ - m3[0, 0], m3[0, 1], m3[0, 2], col3.x, - m3[1, 0], m3[1, 1], m3[1, 2], col3.y, - m3[2, 0], m3[2, 1], m3[2, 2], col3.z, - 0, 0, 0, 1, - ]) - - -# call e.g. TMat32[int]().randomized() to get a random matrix -template makeRandomInit(mattype: typedesc) = - proc randomized*[T: SomeInteger](m: mattype[T]): mattype[T] = - for i in 0 ..< result.data.len: - result.data[i] = rand(low(typeof(m.data[0])) .. high(typeof(m.data[0]))) - proc randomized*[T: SomeFloat](m: mattype[T]): mattype[T] = - for i in 0 ..< result.data.len: - result.data[i] = rand(T(1.0)) - -makeRandomInit(TMat2) -makeRandomInit(TMat23) -makeRandomInit(TMat32) -makeRandomInit(TMat3) -makeRandomInit(TMat34) -makeRandomInit(TMat43) -makeRandomInit(TMat4) - -func perspective*(fovy, aspect, zNear, zFar: float32): Mat4 = - let tanHalfFovy = tan(fovy / 2) - return Mat4(data:[ - 1 / (aspect * tanHalfFovy), 0, 0, 0, - 0, 1 / tanHalfFovy, 0, 0, - 0, 0, zFar / (zFar - zNear), -(zFar * zNear) / (zFar - zNear), - 0, 0, 1, 1, - ]) - -func ortho*(left, right, top, bottom, zNear, zFar: float32): Mat4 = - Mat4(data:[ - 2 / (right - left), 0, 0, -(right + left) / (right - left), - 0, 2 / (bottom - top), 0, -(bottom + top) / (bottom - top), - 0, 0, 1 / (zFar - zNear), -zNear / (zFar - zNear), - 0, 0, 1, 1, - ]) - -# create an orthographic perspective that will map from -1 .. 1 on all axis and keep a 1:1 aspect ratio -# the smaller dimension (width or height) will always be 1 and the larger dimension will be larger, to keep the ratio -func orthoWindowAspect*(windowAspect: float32): Mat4 = - if windowAspect > 1: - let space = 2 * (windowAspect - 1) / 2 - ortho(-1, 1, -1 - space, 1 + space, 0, 1) - else: - let space = 2 * (1 / windowAspect - 1) / 2 - ortho(-1 - space, 1 + space, -1, 1, 0, 1) - -func position*(mat: Mat4): Vec3f = - mat.col(3).toVec3 - -func scaling*(mat: Mat4): Vec3f = - newVec3f(mat[0, 0], mat[1, 1], mat[2, 2]) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/utils.nim --- a/src/semicongine/core/utils.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -import std/typetraits -import std/strutils -import std/strformat - -func cleanString*(str: openArray[char]): string = - for i in 0 ..< len(str): - if str[i] == char(0): - result = join(str[0 ..< i]) - break - -func toCPointer*[T](list: seq[T]): ptr T = - if list.len > 0: addr(list[0]) else: nil - -proc staticExecChecked*(command: string, input = ""): string {.compileTime.} = - let (output, exitcode) = gorgeEx( - command = command, - input = input) - if exitcode != 0: - raise newException(Exception, &"Running '{command}' produced exit code: {exitcode}" & output) - return output - -func size*[T: seq](list: T): uint64 = - uint64(list.len * sizeof(get(genericParams(typeof(list)), 0))) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/vector.nim --- a/src/semicongine/core/vector.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,326 +0,0 @@ -import std/random -import std/math -import std/strutils -import std/macros -import std/typetraits -import std/tables - -import ./vulkanapi - -type - TVec2*[T: SomeNumber] = array[2, T] - TVec3*[T: SomeNumber] = array[3, T] - TVec4*[T: SomeNumber] = array[4, T] - TVec* = TVec2|TVec3|TVec4 - Vec2f* = TVec2[float32] - Vec3f* = TVec3[float32] - Vec4f* = TVec4[float32] - Vec2i* = TVec2[int32] - Vec3i* = TVec3[int32] - Vec4i* = TVec4[int32] - Vec2u* = TVec2[uint32] - Vec3u* = TVec3[uint32] - Vec4u* = TVec4[uint32] - -converter toVec2*[T: SomeNumber](orig: TVec3[T]|TVec4[T]): TVec2[T] = - TVec2[T]([orig[0], orig[1]]) -converter toVec3*[T: SomeNumber](orig: TVec4[T]): TVec3[T] = - TVec3[T]([orig[0], orig[1], orig[2]]) - -func toVec4*[T: SomeNumber](orig: TVec3[T], value: T = default(T)): TVec4[T] = - TVec4[T]([orig[0], orig[1], orig[2], value]) -func toVec3*[T: SomeNumber](orig: TVec2[T], value: T = default(T)): TVec3[T] = - TVec3[T]([orig[0], orig[1], value]) - -# define some often used constants -func ConstOne2[T: SomeNumber](): auto {.compiletime.} = TVec2[T]([T(1), T(1)]) -func ConstOne3[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(1), T(1), T(1)]) -func ConstOne4[T: SomeNumber](): auto {.compiletime.} = TVec4[T]([T(1), T(1), T(1), T(1)]) -func ConstX[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(1), T(0), T(0)]) -func ConstY[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(0), T(1), T(0)]) -func ConstZ[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(0), T(0), T(1)]) -func ConstR[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(1), T(0), T(0)]) -func ConstG[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(0), T(1), T(0)]) -func ConstB[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(0), T(0), T(1)]) - -func newVec2f*(x=0'f32, y=0'f32): auto = - Vec2f([x, y]) -func newVec3f*(x=0'f32, y=0'f32, z=0'f32): auto = - Vec3f([x, y, z]) -func newVec4f*(x=0'f32, y=0'f32, z=0'f32, a=0'f32): auto = - Vec4f([x, y, z, a]) -func newVec2i*(x=0'i32, y=0'i32): auto = - Vec2i([x, y]) -func newVec3i*(x=0'i32, y=0'i32, z=0'i32): auto = - Vec3i([x, y, z]) -func newVec4i*(x=0'i32, y=0'i32, z=0'i32, a=0'i32): auto = - Vec4i([x, y, z, a]) -func newVec2u*(x=0'u32, y=0'u32): auto = - Vec2u([x, y]) -func newVec3u*(x=0'u32, y=0'u32, z=0'u32): auto = - Vec3u([x, y, z]) -func newVec4u*(x=0'u32, y=0'u32, z=0'u32, a=0'u32): auto = - Vec4u([x, y, z, a]) - -# generates constants: Xf, Xf32, Xf64, Xi, Xi8, Xi16, Xi32, Xi64 -# Also for Y, Z, R, G, B and One -# not sure if this is necessary or even a good idea... -macro generateAllConsts() = - result = newStmtList() - for component in ["X", "Y", "Z", "R", "G", "B", "One2", "One3", "One4"]: - for theType in ["int", "int8", "int16", "int32", "int64", "float", "float32", "float64"]: - var typename = theType[0 .. 0] - if theType[^2].isDigit: - typename = typename & theType[^2] - if theType[^1].isDigit: - typename = typename & theType[^1] - result.add( - newConstStmt( - postfix(ident(component & typename), "*"), - newCall(nnkBracketExpr.newTree(ident("Const" & component), ident(theType))) - ) - ) - -generateAllConsts() - -const X* = ConstX[float32]() -const Y* = ConstY[float32]() -const Z* = ConstZ[float32]() -const One2* = ConstOne2[float32]() -const One3* = ConstOne3[float32]() -const One4* = ConstOne4[float32]() - -func newVec2*[T](x, y: T): auto = TVec2([x, y]) -func newVec3*[T](x, y, z: T): auto = TVec3([x, y, z]) -func newVec4*[T](x, y, z, w: T): auto = TVec4([x, y, z, w]) - -func to*[T](v: TVec2): auto = TVec2([T(v[0]), T(v[1])]) -func to*[T](v: TVec3): auto = TVec3([T(v[0]), T(v[1]), T(v[2])]) -func to*[T](v: TVec4): auto = TVec4([T(v[0]), T(v[1]), T(v[2]), T(v[3])]) - -func toString[T](value: T): string = - var items: seq[string] - for item in value: - items.add($item) - $T & "(" & join(items, " ") & ")" - -func `$`*(v: TVec2[SomeNumber]): string = toString[TVec2[SomeNumber]](v) -func `$`*(v: TVec3[SomeNumber]): string = toString[TVec3[SomeNumber]](v) -func `$`*(v: TVec4[SomeNumber]): string = toString[TVec4[SomeNumber]](v) - -func length*(vec: TVec2[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[1]) -func length*(vec: TVec2[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[ - 1] * vec[1])) -func length*(vec: TVec3[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[ - 1] + vec[2] * vec[2]) -func length*(vec: TVec3[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[ - 1] * vec[1] + vec[2] * vec[2])) -func length*(vec: TVec4[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[ - 1] + vec[2] * vec[2] + vec[3] * vec[3]) -func length*(vec: TVec4[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[ - 1] * vec[1] + vec[2] * vec[2] + vec[3] * vec[3])) - -func normalized*[T: SomeFloat](vec: TVec2[T]): auto = - let l = vec.length - if l == 0: vec - else: TVec2[T]([vec[0] / l, vec[1] / l]) -func normalized*[T: SomeFloat](vec: TVec3[T]): auto = - let l = vec.length - if l == 0: return vec - else: TVec3[T]([vec[0] / l, vec[1] / l, vec[2] / l]) -func normalized*[T: SomeFloat](vec: TVec4[T]): auto = - let l = vec.length - if l == 0: return vec - else: TVec4[T]([vec[0] / l, vec[1] / l, vec[2] / l, vec[3] / l]) - -# scalar operations -func `+`*(a: TVec2, b: SomeNumber): auto = TVec2([a[0] + b, a[1] + b]) -func `+`*(a: TVec3, b: SomeNumber): auto = TVec3([a[0] + b, a[1] + b, a[2] + b]) -func `+`*(a: TVec4, b: SomeNumber): auto = TVec4([a[0] + b, a[1] + b, a[2] + b, - a[3] + b]) -func `-`*(a: TVec2, b: SomeNumber): auto = TVec2([a[0] - b, a[1] - b]) -func `-`*(a: TVec3, b: SomeNumber): auto = TVec3([a[0] - b, a[1] - b, a[2] - b]) -func `-`*(a: TVec4, b: SomeNumber): auto = TVec4([a[0] - b, a[1] - b, a[2] - b, - a[3] - b]) -func `*`*(a: TVec2, b: SomeNumber): auto = TVec2([a[0] * b, a[1] * b]) -func `*`*(a: TVec3, b: SomeNumber): auto = TVec3([a[0] * b, a[1] * b, a[2] * b]) -func `*`*(a: TVec4, b: SomeNumber): auto = TVec4([a[0] * b, a[1] * b, a[2] * b, - a[3] * b]) -func `/`*[T: SomeInteger](a: TVec2[T], b: SomeInteger): auto = TVec2([a[ - 0] div b, a[1] div b]) -func `/`*[T: SomeFloat](a: TVec2[T], b: SomeFloat): auto = TVec2([a[0] / b, a[1] / b]) -func `/`*[T: SomeInteger](a: TVec3[T], b: SomeInteger): auto = TVec3([a[ - 0] div b, a[1] div b, a[2] div b]) -func `/`*[T: SomeFloat](a: TVec3[T], b: SomeFloat): auto = TVec3([a[0] / b, a[ - 1] / b, a[2] / b]) -func `/`*[T: SomeInteger](a: TVec4[T], b: SomeInteger): auto = TVec4([a[ - 0] div b, a[1] div b, a[2] div b, a[3] div b]) -func `/`*[T: SomeFloat](a: TVec4[T], b: SomeFloat): auto = TVec4([a[0] / b, a[ - 1] / b, a[2] / b, a[3] / b]) - -func `+`*(a: SomeNumber, b: TVec2): auto = TVec2([a + b[0], a + b[1]]) -func `+`*(a: SomeNumber, b: TVec3): auto = TVec3([a + b[0], a + b[1], a + b[2]]) -func `+`*(a: SomeNumber, b: TVec4): auto = TVec4([a + b[0], a + b[1], a + b[2], - a + b[3]]) -func `-`*(a: SomeNumber, b: TVec2): auto = TVec2([a - b[0], a - b[1]]) -func `-`*(a: SomeNumber, b: TVec3): auto = TVec3([a - b[0], a - b[1], a - b[2]]) -func `-`*(a: SomeNumber, b: TVec4): auto = TVec4([a - b[0], a - b[1], a - b[2], - a - b[3]]) -func `*`*(a: SomeNumber, b: TVec2): auto = TVec2([a * b[0], a * b[1]]) -func `*`*(a: SomeNumber, b: TVec3): auto = TVec3([a * b[0], a * b[1], a * b[2]]) -func `*`*(a: SomeNumber, b: TVec4): auto = TVec4([a * b[0], a * b[1], a * b[2], - a * b[3]]) -func `/`*[T: SomeInteger](a: SomeInteger, b: TVec2[T]): auto = TVec2([a div b[ - 0], a div b[1]]) -func `/`*[T: SomeFloat](a: SomeFloat, b: TVec2[T]): auto = TVec2([a / b[0], a / b[1]]) -func `/`*[T: SomeInteger](a: SomeInteger, b: TVec3[T]): auto = TVec3([a div b[ - 0], a div b[1], a div b[2]]) -func `/`*[T: SomeFloat](a: SomeFloat, b: TVec3[T]): auto = TVec3([a / b[0], a / - b[1], a / b[2]]) -func `/`*[T: SomeInteger](a: SomeInteger, b: TVec4[T]): auto = TVec4([a div b[ - 0], a div b[1], a div b[2], a div b[3]]) -func `/`*[T: SomeFloat](a: SomeFloat, b: TVec4[T]): auto = TVec4([a / b[0], a / - b[1], a / b[2], a / b[3]]) - -# compontent-wise operations -func `+`*(a, b: TVec2): auto = TVec2([a[0] + b[0], a[1] + b[1]]) -func `+`*(a, b: TVec3): auto = TVec3([a[0] + b[0], a[1] + b[1], a[2] + b[2]]) -func `+`*(a, b: TVec4): auto = TVec4([a[0] + b[0], a[1] + b[1], a[2] + b[2], a[ - 3] + b[3]]) -func `-`*(a: TVec2): auto = TVec2([-a[0], -a[1]]) -func `-`*(a: TVec3): auto = TVec3([-a[0], -a[1], -a[2]]) -func `-`*(a: TVec4): auto = TVec4([-a[0], -a[1], -a[2], -a[3]]) -func `-`*(a, b: TVec2): auto = TVec2([a[0] - b[0], a[1] - b[1]]) -func `-`*(a, b: TVec3): auto = TVec3([a[0] - b[0], a[1] - b[1], a[2] - b[2]]) -func `-`*(a, b: TVec4): auto = TVec4([a[0] - b[0], a[1] - b[1], a[2] - b[2], a[ - 3] - b[3]]) -func `*`*(a, b: TVec2): auto = TVec2([a[0] * b[0], a[1] * b[1]]) -func `*`*(a, b: TVec3): auto = TVec3([a[0] * b[0], a[1] * b[1], a[2] * b[2]]) -func `*`*(a, b: TVec4): auto = TVec4([a[0] * b[0], a[1] * b[1], a[2] * b[2], a[ - 3] * b[3]]) -func `/`*[T: SomeInteger](a, b: TVec2[T]): auto = TVec2([a[0] div b[0], a[ - 1] div b[1]]) -func `/`*[T: SomeFloat](a, b: TVec2[T]): auto = TVec2([a[0] / b[0], a[1] / b[1]]) -func `/`*[T: SomeInteger](a, b: TVec3[T]): auto = TVec3([a[0] div b[0], a[ - 1] div b[1], a[2] div b[2]]) -func `/`*[T: SomeFloat](a, b: TVec3[T]): auto = TVec3([a[0] / b[0], a[1] / b[1], - a[2] / b[2]]) -func `/`*[T: SomeInteger](a, b: TVec4[T]): auto = TVec4([a[0] div b[0], a[ - 1] div b[1], a[2] div b[2], a[3] div b[3]]) -func `/`*[T: SomeFloat](a, b: TVec4[T]): auto = TVec4([a[0] / b[0], a[1] / b[1], - a[2] / b[2], a[3] / b[3]]) - -# special operations -func pow*(a: TVec2, b: SomeNumber): auto = - TVec2([pow(a[0], b), pow(a[1], b)]) -func pow*(a: TVec3, b: SomeNumber): auto = - TVec3([pow(a[0], b), pow(a[1], b), pow(a[2], b)]) -func pow*(a: TVec4, b: SomeNumber): auto = - TVec4([pow(a[0], b), pow(a[1], b), pow(a[2], b), pow(a[3], b)]) -func dot*(a, b: TVec2): auto = a[0] * b[0] + a[1] * b[1] -func dot*(a, b: TVec3): auto = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] -func dot*(a, b: TVec4): auto = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] -func cross*(a, b: TVec3): auto = TVec3([ - a[1] * b[2] - a[2] * b[1], - a[2] * b[0] - a[0] * b[2], - a[0] * b[1] - a[1] * b[0], -]) - - -# macro to allow creation of new vectors by specifying vector components as attributes -# e.g. myVec.xxy will return a new Vec3 that contains the components x, x an y of the original vector -# (instead of x, y, z for a simple copy) -proc vectorAttributeAccessor(accessor: string): seq[NimNode] = - const ACCESSOR_INDICES = { - 'x': 0, - 'y': 1, - 'z': 2, - 'w': 3, - 'r': 0, - 'g': 1, - 'b': 2, - 'a': 3, - }.toTable - var getterCode, setterCode: NimNode - let accessorvalue = accessor - - if accessorvalue.len == 0: - raise newException(Exception, "empty attribute") - elif accessorvalue.len == 1: - getterCode = nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[accessorvalue[0]])) - setterCode = nnkStmtList.newTree( - nnkAsgn.newTree( - nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[accessorvalue[0]])), ident("value")) - ) - if accessorvalue.len > 1: - var attrs = nnkBracket.newTree() - for attrname in accessorvalue: - attrs.add(nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[attrname]))) - getterCode = nnkCall.newTree(ident("TVec" & $accessorvalue.len), attrs) - setterCode = nnkStmtList.newTree() - var i = 0 - for attrname in accessorvalue: - setterCode.add nnkAsgn.newTree( - nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[attrname])), - nnkBracketExpr.newTree(ident("value"), newLit(i)), - ) - inc i - - result.add newProc( - name = nnkPostfix.newTree(ident("*"), ident(accessor)), - params = [ident("auto"), nnkIdentDefs.newTree(ident("vec"), ident("TVec"), newEmptyNode())], - body = newStmtList(getterCode), - procType = nnkFuncDef, - ) - - result.add nnkFuncDef.newTree( - nnkPostfix.newTree( - newIdentNode("*"), - nnkAccQuoted.newTree(newIdentNode(accessor), newIdentNode("=")) - ), - newEmptyNode(), - nnkGenericParams.newTree(nnkIdentDefs.newTree(newIdentNode("T"), newEmptyNode(), newEmptyNode())), - nnkFormalParams.newTree( - newEmptyNode(), - nnkIdentDefs.newTree( newIdentNode("vec"), nnkVarTy.newTree(newIdentNode("TVec")), newEmptyNode()), - nnkIdentDefs.newTree( newIdentNode("value"), newIdentNode("T"), newEmptyNode()) - ), - newEmptyNode(), - newEmptyNode(), - setterCode - ) - -macro createVectorAttribAccessorFuncs() = - const COORD_ATTRS = ["x", "y", "z", "w"] - const COLOR_ATTRS = ["r", "g", "b", "a"] - result = nnkStmtList.newTree() - for attlist in [COORD_ATTRS, COLOR_ATTRS]: - for i in attlist: - result.add(vectorAttributeAccessor(i)) - for j in attlist: - result.add(vectorAttributeAccessor(i & j)) - for k in attlist: - result.add(vectorAttributeAccessor(i & j & k)) - for l in attlist: - result.add(vectorAttributeAccessor(i & j & k & l)) - -createVectorAttribAccessorFuncs() - -# call e.g. Vec2[int]().randomized() to get a random matrix -template makeRandomInit(mattype: typedesc) = - proc randomized*[T: SomeInteger](m: mattype[T]): mattype[T] = - for i in 0 ..< result.len: - result[i] = rand(low(typeof(m[0])) .. high(typeof(m[0]))) - proc randomized*[T: SomeFloat](m: mattype[T]): mattype[T] = - for i in 0 ..< result.len: - result[i] = rand(1.0) - -makeRandomInit(TVec2) -makeRandomInit(TVec3) -makeRandomInit(TVec4) - -converter Vec2VkExtent*(vec: TVec2[uint32]): VkExtent2D = VkExtent2D(width: vec[0], height: vec[1]) -converter Vec3VkExtent*(vec: TVec2[uint32]): VkExtent3D = VkExtent3D(width: vec[0], height: vec[1], depth: vec[2]) - -func angleBetween*(a, b: Vec3f): float32 = - arccos(a.dot(b) / (a.length * b.length)) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/core/vulkanapi.nim --- a/src/semicongine/core/vulkanapi.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12067 +0,0 @@ -import std/dynlib -import std/tables -import std/strutils -import std/logging -import std/typetraits -import std/macros -type - VkHandle* = distinct uint - VkNonDispatchableHandle* = distinct uint -when defined(linux): - let vulkanLib* = loadLib("libvulkan.so.1") -when defined(windows): - let vulkanLib* = loadLib("vulkan-1.dll") -if vulkanLib == nil: - raise newException(Exception, "Unable to load vulkan library") -func VK_MAKE_API_VERSION*(variant: uint32, major: uint32, minor: uint32, patch: uint32): uint32 {.compileTime.} = - (variant shl 29) or (major shl 22) or (minor shl 12) or patch - -template checkVkResult*(call: untyped) = - when defined(release): - discard call - else: - # yes, a bit cheap, but this is only for nice debug output - var callstr = astToStr(call).replace("\n", "") - while callstr.find(" ") >= 0: - callstr = callstr.replace(" ", " ") - debug "Calling vulkan: ", callstr - let value = call - if value != VK_SUCCESS: - error "Vulkan error: ", astToStr(call), " returned ", $value - raise newException(Exception, "Vulkan error: " & astToStr(call) & - " returned " & $value) -# custom enum iteration (for enum values > 2^16) -macro enumFullRange(a: typed): untyped = - newNimNode(nnkBracket).add(a.getType[1][1..^1]) - -iterator items*[T: HoleyEnum](E: typedesc[T]): T = - for a in enumFullRange(E): yield a -const - VK_MAX_PHYSICAL_DEVICE_NAME_SIZE*: uint32 = 256 - VK_UUID_SIZE*: uint32 = 16 - VK_LUID_SIZE*: uint32 = 8 - VK_LUID_SIZE_KHR* = VK_LUID_SIZE - VK_MAX_EXTENSION_NAME_SIZE*: uint32 = 256 - VK_MAX_DESCRIPTION_SIZE*: uint32 = 256 - VK_MAX_MEMORY_TYPES*: uint32 = 32 - VK_MAX_MEMORY_HEAPS*: uint32 = 16 - VK_LOD_CLAMP_NONE*: float32 = 1000.0F - VK_REMAINING_MIP_LEVELS*: uint32 = not 0'u32 - VK_REMAINING_ARRAY_LAYERS*: uint32 = not 0'u32 - VK_REMAINING_3D_SLICES_EXT*: uint32 = not 0'u32 - VK_WHOLE_SIZE*: uint64 = not 0'u64 - VK_ATTACHMENT_UNUSED*: uint32 = not 0'u32 - VK_TRUE*: uint32 = 1 - VK_FALSE*: uint32 = 0 - VK_QUEUE_FAMILY_IGNORED*: uint32 = not 0'u32 - VK_QUEUE_FAMILY_EXTERNAL*: uint32 = not 1'u32 - VK_QUEUE_FAMILY_EXTERNAL_KHR* = VK_QUEUE_FAMILY_EXTERNAL - VK_QUEUE_FAMILY_FOREIGN_EXT*: uint32 = not 2'u32 - VK_SUBPASS_EXTERNAL*: uint32 = not 0'u32 - VK_MAX_DEVICE_GROUP_SIZE*: uint32 = 32 - VK_MAX_DEVICE_GROUP_SIZE_KHR* = VK_MAX_DEVICE_GROUP_SIZE - VK_MAX_DRIVER_NAME_SIZE*: uint32 = 256 - VK_MAX_DRIVER_NAME_SIZE_KHR* = VK_MAX_DRIVER_NAME_SIZE - VK_MAX_DRIVER_INFO_SIZE*: uint32 = 256 - VK_MAX_DRIVER_INFO_SIZE_KHR* = VK_MAX_DRIVER_INFO_SIZE - VK_SHADER_UNUSED_KHR*: uint32 = not 0'u32 - VK_SHADER_UNUSED_NV* = VK_SHADER_UNUSED_KHR - VK_MAX_GLOBAL_PRIORITY_SIZE_KHR*: uint32 = 16 - VK_MAX_GLOBAL_PRIORITY_SIZE_EXT* = VK_MAX_GLOBAL_PRIORITY_SIZE_KHR - VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT*: uint32 = 32 -type - ANativeWindow* = object - AHardwareBuffer* = object - CAMetalLayer* = object - MTLDevice_id* = object - MTLCommandQueue_id* = object - MTLBuffer_id* = object - MTLTexture_id* = object - MTLSharedEvent_id* = object - IOSurfaceRef* = object - VkSampleMask* = uint32 - VkBool32* = uint32 - VkFlags* = uint32 - VkFlags64* = uint64 - VkDeviceSize* = uint64 - VkDeviceAddress* = uint64 - VkInstance* = distinct VkHandle - VkPhysicalDevice* = distinct VkHandle - VkDevice* = distinct VkHandle - VkQueue* = distinct VkHandle - VkCommandBuffer* = distinct VkHandle - VkDeviceMemory* = distinct VkNonDispatchableHandle - VkCommandPool* = distinct VkNonDispatchableHandle - VkBuffer* = distinct VkNonDispatchableHandle - VkBufferView* = distinct VkNonDispatchableHandle - VkImage* = distinct VkNonDispatchableHandle - VkImageView* = distinct VkNonDispatchableHandle - VkShaderModule* = distinct VkNonDispatchableHandle - VkPipeline* = distinct VkNonDispatchableHandle - VkPipelineLayout* = distinct VkNonDispatchableHandle - VkSampler* = distinct VkNonDispatchableHandle - VkDescriptorSet* = distinct VkNonDispatchableHandle - VkDescriptorSetLayout* = distinct VkNonDispatchableHandle - VkDescriptorPool* = distinct VkNonDispatchableHandle - VkFence* = distinct VkNonDispatchableHandle - VkSemaphore* = distinct VkNonDispatchableHandle - VkEvent* = distinct VkNonDispatchableHandle - VkQueryPool* = distinct VkNonDispatchableHandle - VkFramebuffer* = distinct VkNonDispatchableHandle - VkRenderPass* = distinct VkNonDispatchableHandle - VkPipelineCache* = distinct VkNonDispatchableHandle - VkIndirectCommandsLayoutNV* = distinct VkNonDispatchableHandle - VkDescriptorUpdateTemplate* = distinct VkNonDispatchableHandle - VkSamplerYcbcrConversion* = distinct VkNonDispatchableHandle - VkValidationCacheEXT* = distinct VkNonDispatchableHandle - VkAccelerationStructureKHR* = distinct VkNonDispatchableHandle - VkAccelerationStructureNV* = distinct VkNonDispatchableHandle - VkPerformanceConfigurationINTEL* = distinct VkNonDispatchableHandle - VkBufferCollectionFUCHSIA* = distinct VkNonDispatchableHandle - VkDeferredOperationKHR* = distinct VkNonDispatchableHandle - VkPrivateDataSlot* = distinct VkNonDispatchableHandle - VkCuModuleNVX* = distinct VkNonDispatchableHandle - VkCuFunctionNVX* = distinct VkNonDispatchableHandle - VkOpticalFlowSessionNV* = distinct VkNonDispatchableHandle - VkMicromapEXT* = distinct VkNonDispatchableHandle - VkDisplayKHR* = distinct VkNonDispatchableHandle - VkDisplayModeKHR* = distinct VkNonDispatchableHandle - VkSurfaceKHR* = distinct VkNonDispatchableHandle - VkSwapchainKHR* = distinct VkNonDispatchableHandle - VkDebugReportCallbackEXT* = distinct VkNonDispatchableHandle - VkDebugUtilsMessengerEXT* = distinct VkNonDispatchableHandle - VkVideoSessionKHR* = distinct VkNonDispatchableHandle - VkVideoSessionParametersKHR* = distinct VkNonDispatchableHandle - VkSemaphoreSciSyncPoolNV* = distinct VkNonDispatchableHandle - VkRemoteAddressNV* = pointer -proc `$`*(handle: VkInstance): string = "VkInstance(" & $(uint(handle)) & ")" -proc valid*(handle: VkInstance): bool = uint(handle) != 0 -proc reset*(handle: var VkInstance) = handle = VkInstance(0) -proc `==`*(a, b: VkInstance): bool = uint(a) == uint(b) -proc `$`*(handle: VkPhysicalDevice): string = "VkPhysicalDevice(" & $(uint(handle)) & ")" -proc valid*(handle: VkPhysicalDevice): bool = uint(handle) != 0 -proc reset*(handle: var VkPhysicalDevice) = handle = VkPhysicalDevice(0) -proc `==`*(a, b: VkPhysicalDevice): bool = uint(a) == uint(b) -proc `$`*(handle: VkDevice): string = "VkDevice(" & $(uint(handle)) & ")" -proc valid*(handle: VkDevice): bool = uint(handle) != 0 -proc reset*(handle: var VkDevice) = handle = VkDevice(0) -proc `==`*(a, b: VkDevice): bool = uint(a) == uint(b) -proc `$`*(handle: VkQueue): string = "VkQueue(" & $(uint(handle)) & ")" -proc valid*(handle: VkQueue): bool = uint(handle) != 0 -proc reset*(handle: var VkQueue) = handle = VkQueue(0) -proc `==`*(a, b: VkQueue): bool = uint(a) == uint(b) -proc `$`*(handle: VkCommandBuffer): string = "VkCommandBuffer(" & $(uint(handle)) & ")" -proc valid*(handle: VkCommandBuffer): bool = uint(handle) != 0 -proc reset*(handle: var VkCommandBuffer) = handle = VkCommandBuffer(0) -proc `==`*(a, b: VkCommandBuffer): bool = uint(a) == uint(b) -proc `$`*(handle: VkDeviceMemory): string = "VkDeviceMemory(" & $(uint(handle)) & ")" -proc valid*(handle: VkDeviceMemory): bool = uint(handle) != 0 -proc reset*(handle: var VkDeviceMemory) = handle = VkDeviceMemory(0) -proc `==`*(a, b: VkDeviceMemory): bool = uint(a) == uint(b) -proc `$`*(handle: VkCommandPool): string = "VkCommandPool(" & $(uint(handle)) & ")" -proc valid*(handle: VkCommandPool): bool = uint(handle) != 0 -proc reset*(handle: var VkCommandPool) = handle = VkCommandPool(0) -proc `==`*(a, b: VkCommandPool): bool = uint(a) == uint(b) -proc `$`*(handle: VkBuffer): string = "VkBuffer(" & $(uint(handle)) & ")" -proc valid*(handle: VkBuffer): bool = uint(handle) != 0 -proc reset*(handle: var VkBuffer) = handle = VkBuffer(0) -proc `==`*(a, b: VkBuffer): bool = uint(a) == uint(b) -proc `$`*(handle: VkBufferView): string = "VkBufferView(" & $(uint(handle)) & ")" -proc valid*(handle: VkBufferView): bool = uint(handle) != 0 -proc reset*(handle: var VkBufferView) = handle = VkBufferView(0) -proc `==`*(a, b: VkBufferView): bool = uint(a) == uint(b) -proc `$`*(handle: VkImage): string = "VkImage(" & $(uint(handle)) & ")" -proc valid*(handle: VkImage): bool = uint(handle) != 0 -proc reset*(handle: var VkImage) = handle = VkImage(0) -proc `==`*(a, b: VkImage): bool = uint(a) == uint(b) -proc `$`*(handle: VkImageView): string = "VkImageView(" & $(uint(handle)) & ")" -proc valid*(handle: VkImageView): bool = uint(handle) != 0 -proc reset*(handle: var VkImageView) = handle = VkImageView(0) -proc `==`*(a, b: VkImageView): bool = uint(a) == uint(b) -proc `$`*(handle: VkShaderModule): string = "VkShaderModule(" & $(uint(handle)) & ")" -proc valid*(handle: VkShaderModule): bool = uint(handle) != 0 -proc reset*(handle: var VkShaderModule) = handle = VkShaderModule(0) -proc `==`*(a, b: VkShaderModule): bool = uint(a) == uint(b) -proc `$`*(handle: VkPipeline): string = "VkPipeline(" & $(uint(handle)) & ")" -proc valid*(handle: VkPipeline): bool = uint(handle) != 0 -proc reset*(handle: var VkPipeline) = handle = VkPipeline(0) -proc `==`*(a, b: VkPipeline): bool = uint(a) == uint(b) -proc `$`*(handle: VkPipelineLayout): string = "VkPipelineLayout(" & $(uint(handle)) & ")" -proc valid*(handle: VkPipelineLayout): bool = uint(handle) != 0 -proc reset*(handle: var VkPipelineLayout) = handle = VkPipelineLayout(0) -proc `==`*(a, b: VkPipelineLayout): bool = uint(a) == uint(b) -proc `$`*(handle: VkSampler): string = "VkSampler(" & $(uint(handle)) & ")" -proc valid*(handle: VkSampler): bool = uint(handle) != 0 -proc reset*(handle: var VkSampler) = handle = VkSampler(0) -proc `==`*(a, b: VkSampler): bool = uint(a) == uint(b) -proc `$`*(handle: VkDescriptorSet): string = "VkDescriptorSet(" & $(uint(handle)) & ")" -proc valid*(handle: VkDescriptorSet): bool = uint(handle) != 0 -proc reset*(handle: var VkDescriptorSet) = handle = VkDescriptorSet(0) -proc `==`*(a, b: VkDescriptorSet): bool = uint(a) == uint(b) -proc `$`*(handle: VkDescriptorSetLayout): string = "VkDescriptorSetLayout(" & $(uint(handle)) & ")" -proc valid*(handle: VkDescriptorSetLayout): bool = uint(handle) != 0 -proc reset*(handle: var VkDescriptorSetLayout) = handle = VkDescriptorSetLayout(0) -proc `==`*(a, b: VkDescriptorSetLayout): bool = uint(a) == uint(b) -proc `$`*(handle: VkDescriptorPool): string = "VkDescriptorPool(" & $(uint(handle)) & ")" -proc valid*(handle: VkDescriptorPool): bool = uint(handle) != 0 -proc reset*(handle: var VkDescriptorPool) = handle = VkDescriptorPool(0) -proc `==`*(a, b: VkDescriptorPool): bool = uint(a) == uint(b) -proc `$`*(handle: VkFence): string = "VkFence(" & $(uint(handle)) & ")" -proc valid*(handle: VkFence): bool = uint(handle) != 0 -proc reset*(handle: var VkFence) = handle = VkFence(0) -proc `==`*(a, b: VkFence): bool = uint(a) == uint(b) -proc `$`*(handle: VkSemaphore): string = "VkSemaphore(" & $(uint(handle)) & ")" -proc valid*(handle: VkSemaphore): bool = uint(handle) != 0 -proc reset*(handle: var VkSemaphore) = handle = VkSemaphore(0) -proc `==`*(a, b: VkSemaphore): bool = uint(a) == uint(b) -proc `$`*(handle: VkEvent): string = "VkEvent(" & $(uint(handle)) & ")" -proc valid*(handle: VkEvent): bool = uint(handle) != 0 -proc reset*(handle: var VkEvent) = handle = VkEvent(0) -proc `==`*(a, b: VkEvent): bool = uint(a) == uint(b) -proc `$`*(handle: VkQueryPool): string = "VkQueryPool(" & $(uint(handle)) & ")" -proc valid*(handle: VkQueryPool): bool = uint(handle) != 0 -proc reset*(handle: var VkQueryPool) = handle = VkQueryPool(0) -proc `==`*(a, b: VkQueryPool): bool = uint(a) == uint(b) -proc `$`*(handle: VkFramebuffer): string = "VkFramebuffer(" & $(uint(handle)) & ")" -proc valid*(handle: VkFramebuffer): bool = uint(handle) != 0 -proc reset*(handle: var VkFramebuffer) = handle = VkFramebuffer(0) -proc `==`*(a, b: VkFramebuffer): bool = uint(a) == uint(b) -proc `$`*(handle: VkRenderPass): string = "VkRenderPass(" & $(uint(handle)) & ")" -proc valid*(handle: VkRenderPass): bool = uint(handle) != 0 -proc reset*(handle: var VkRenderPass) = handle = VkRenderPass(0) -proc `==`*(a, b: VkRenderPass): bool = uint(a) == uint(b) -proc `$`*(handle: VkPipelineCache): string = "VkPipelineCache(" & $(uint(handle)) & ")" -proc valid*(handle: VkPipelineCache): bool = uint(handle) != 0 -proc reset*(handle: var VkPipelineCache) = handle = VkPipelineCache(0) -proc `==`*(a, b: VkPipelineCache): bool = uint(a) == uint(b) -proc `$`*(handle: VkIndirectCommandsLayoutNV): string = "VkIndirectCommandsLayoutNV(" & $(uint(handle)) & ")" -proc valid*(handle: VkIndirectCommandsLayoutNV): bool = uint(handle) != 0 -proc reset*(handle: var VkIndirectCommandsLayoutNV) = handle = VkIndirectCommandsLayoutNV(0) -proc `==`*(a, b: VkIndirectCommandsLayoutNV): bool = uint(a) == uint(b) -proc `$`*(handle: VkDescriptorUpdateTemplate): string = "VkDescriptorUpdateTemplate(" & $(uint(handle)) & ")" -proc valid*(handle: VkDescriptorUpdateTemplate): bool = uint(handle) != 0 -proc reset*(handle: var VkDescriptorUpdateTemplate) = handle = VkDescriptorUpdateTemplate(0) -proc `==`*(a, b: VkDescriptorUpdateTemplate): bool = uint(a) == uint(b) -proc `$`*(handle: VkSamplerYcbcrConversion): string = "VkSamplerYcbcrConversion(" & $(uint(handle)) & ")" -proc valid*(handle: VkSamplerYcbcrConversion): bool = uint(handle) != 0 -proc reset*(handle: var VkSamplerYcbcrConversion) = handle = VkSamplerYcbcrConversion(0) -proc `==`*(a, b: VkSamplerYcbcrConversion): bool = uint(a) == uint(b) -proc `$`*(handle: VkValidationCacheEXT): string = "VkValidationCacheEXT(" & $(uint(handle)) & ")" -proc valid*(handle: VkValidationCacheEXT): bool = uint(handle) != 0 -proc reset*(handle: var VkValidationCacheEXT) = handle = VkValidationCacheEXT(0) -proc `==`*(a, b: VkValidationCacheEXT): bool = uint(a) == uint(b) -proc `$`*(handle: VkAccelerationStructureKHR): string = "VkAccelerationStructureKHR(" & $(uint(handle)) & ")" -proc valid*(handle: VkAccelerationStructureKHR): bool = uint(handle) != 0 -proc reset*(handle: var VkAccelerationStructureKHR) = handle = VkAccelerationStructureKHR(0) -proc `==`*(a, b: VkAccelerationStructureKHR): bool = uint(a) == uint(b) -proc `$`*(handle: VkAccelerationStructureNV): string = "VkAccelerationStructureNV(" & $(uint(handle)) & ")" -proc valid*(handle: VkAccelerationStructureNV): bool = uint(handle) != 0 -proc reset*(handle: var VkAccelerationStructureNV) = handle = VkAccelerationStructureNV(0) -proc `==`*(a, b: VkAccelerationStructureNV): bool = uint(a) == uint(b) -proc `$`*(handle: VkPerformanceConfigurationINTEL): string = "VkPerformanceConfigurationINTEL(" & $(uint(handle)) & ")" -proc valid*(handle: VkPerformanceConfigurationINTEL): bool = uint(handle) != 0 -proc reset*(handle: var VkPerformanceConfigurationINTEL) = handle = VkPerformanceConfigurationINTEL(0) -proc `==`*(a, b: VkPerformanceConfigurationINTEL): bool = uint(a) == uint(b) -proc `$`*(handle: VkBufferCollectionFUCHSIA): string = "VkBufferCollectionFUCHSIA(" & $(uint(handle)) & ")" -proc valid*(handle: VkBufferCollectionFUCHSIA): bool = uint(handle) != 0 -proc reset*(handle: var VkBufferCollectionFUCHSIA) = handle = VkBufferCollectionFUCHSIA(0) -proc `==`*(a, b: VkBufferCollectionFUCHSIA): bool = uint(a) == uint(b) -proc `$`*(handle: VkDeferredOperationKHR): string = "VkDeferredOperationKHR(" & $(uint(handle)) & ")" -proc valid*(handle: VkDeferredOperationKHR): bool = uint(handle) != 0 -proc reset*(handle: var VkDeferredOperationKHR) = handle = VkDeferredOperationKHR(0) -proc `==`*(a, b: VkDeferredOperationKHR): bool = uint(a) == uint(b) -proc `$`*(handle: VkPrivateDataSlot): string = "VkPrivateDataSlot(" & $(uint(handle)) & ")" -proc valid*(handle: VkPrivateDataSlot): bool = uint(handle) != 0 -proc reset*(handle: var VkPrivateDataSlot) = handle = VkPrivateDataSlot(0) -proc `==`*(a, b: VkPrivateDataSlot): bool = uint(a) == uint(b) -proc `$`*(handle: VkCuModuleNVX): string = "VkCuModuleNVX(" & $(uint(handle)) & ")" -proc valid*(handle: VkCuModuleNVX): bool = uint(handle) != 0 -proc reset*(handle: var VkCuModuleNVX) = handle = VkCuModuleNVX(0) -proc `==`*(a, b: VkCuModuleNVX): bool = uint(a) == uint(b) -proc `$`*(handle: VkCuFunctionNVX): string = "VkCuFunctionNVX(" & $(uint(handle)) & ")" -proc valid*(handle: VkCuFunctionNVX): bool = uint(handle) != 0 -proc reset*(handle: var VkCuFunctionNVX) = handle = VkCuFunctionNVX(0) -proc `==`*(a, b: VkCuFunctionNVX): bool = uint(a) == uint(b) -proc `$`*(handle: VkOpticalFlowSessionNV): string = "VkOpticalFlowSessionNV(" & $(uint(handle)) & ")" -proc valid*(handle: VkOpticalFlowSessionNV): bool = uint(handle) != 0 -proc reset*(handle: var VkOpticalFlowSessionNV) = handle = VkOpticalFlowSessionNV(0) -proc `==`*(a, b: VkOpticalFlowSessionNV): bool = uint(a) == uint(b) -proc `$`*(handle: VkMicromapEXT): string = "VkMicromapEXT(" & $(uint(handle)) & ")" -proc valid*(handle: VkMicromapEXT): bool = uint(handle) != 0 -proc reset*(handle: var VkMicromapEXT) = handle = VkMicromapEXT(0) -proc `==`*(a, b: VkMicromapEXT): bool = uint(a) == uint(b) -proc `$`*(handle: VkDisplayKHR): string = "VkDisplayKHR(" & $(uint(handle)) & ")" -proc valid*(handle: VkDisplayKHR): bool = uint(handle) != 0 -proc reset*(handle: var VkDisplayKHR) = handle = VkDisplayKHR(0) -proc `==`*(a, b: VkDisplayKHR): bool = uint(a) == uint(b) -proc `$`*(handle: VkDisplayModeKHR): string = "VkDisplayModeKHR(" & $(uint(handle)) & ")" -proc valid*(handle: VkDisplayModeKHR): bool = uint(handle) != 0 -proc reset*(handle: var VkDisplayModeKHR) = handle = VkDisplayModeKHR(0) -proc `==`*(a, b: VkDisplayModeKHR): bool = uint(a) == uint(b) -proc `$`*(handle: VkSurfaceKHR): string = "VkSurfaceKHR(" & $(uint(handle)) & ")" -proc valid*(handle: VkSurfaceKHR): bool = uint(handle) != 0 -proc reset*(handle: var VkSurfaceKHR) = handle = VkSurfaceKHR(0) -proc `==`*(a, b: VkSurfaceKHR): bool = uint(a) == uint(b) -proc `$`*(handle: VkSwapchainKHR): string = "VkSwapchainKHR(" & $(uint(handle)) & ")" -proc valid*(handle: VkSwapchainKHR): bool = uint(handle) != 0 -proc reset*(handle: var VkSwapchainKHR) = handle = VkSwapchainKHR(0) -proc `==`*(a, b: VkSwapchainKHR): bool = uint(a) == uint(b) -proc `$`*(handle: VkDebugReportCallbackEXT): string = "VkDebugReportCallbackEXT(" & $(uint(handle)) & ")" -proc valid*(handle: VkDebugReportCallbackEXT): bool = uint(handle) != 0 -proc reset*(handle: var VkDebugReportCallbackEXT) = handle = VkDebugReportCallbackEXT(0) -proc `==`*(a, b: VkDebugReportCallbackEXT): bool = uint(a) == uint(b) -proc `$`*(handle: VkDebugUtilsMessengerEXT): string = "VkDebugUtilsMessengerEXT(" & $(uint(handle)) & ")" -proc valid*(handle: VkDebugUtilsMessengerEXT): bool = uint(handle) != 0 -proc reset*(handle: var VkDebugUtilsMessengerEXT) = handle = VkDebugUtilsMessengerEXT(0) -proc `==`*(a, b: VkDebugUtilsMessengerEXT): bool = uint(a) == uint(b) -proc `$`*(handle: VkVideoSessionKHR): string = "VkVideoSessionKHR(" & $(uint(handle)) & ")" -proc valid*(handle: VkVideoSessionKHR): bool = uint(handle) != 0 -proc reset*(handle: var VkVideoSessionKHR) = handle = VkVideoSessionKHR(0) -proc `==`*(a, b: VkVideoSessionKHR): bool = uint(a) == uint(b) -proc `$`*(handle: VkVideoSessionParametersKHR): string = "VkVideoSessionParametersKHR(" & $(uint(handle)) & ")" -proc valid*(handle: VkVideoSessionParametersKHR): bool = uint(handle) != 0 -proc reset*(handle: var VkVideoSessionParametersKHR) = handle = VkVideoSessionParametersKHR(0) -proc `==`*(a, b: VkVideoSessionParametersKHR): bool = uint(a) == uint(b) -proc `$`*(handle: VkSemaphoreSciSyncPoolNV): string = "VkSemaphoreSciSyncPoolNV(" & $(uint(handle)) & ")" -proc valid*(handle: VkSemaphoreSciSyncPoolNV): bool = uint(handle) != 0 -proc reset*(handle: var VkSemaphoreSciSyncPoolNV) = handle = VkSemaphoreSciSyncPoolNV(0) -proc `==`*(a, b: VkSemaphoreSciSyncPoolNV): bool = uint(a) == uint(b) -type - VkFramebufferCreateFlags* = distinct VkFlags - VkQueryPoolCreateFlags* = distinct VkFlags - VkRenderPassCreateFlags* = distinct VkFlags - VkSamplerCreateFlags* = distinct VkFlags - VkPipelineLayoutCreateFlags* = distinct VkFlags - VkPipelineCacheCreateFlags* = distinct VkFlags - VkPipelineDepthStencilStateCreateFlags* = distinct VkFlags - VkPipelineDynamicStateCreateFlags* = distinct VkFlags - VkPipelineColorBlendStateCreateFlags* = distinct VkFlags - VkPipelineMultisampleStateCreateFlags* = distinct VkFlags - VkPipelineRasterizationStateCreateFlags* = distinct VkFlags - VkPipelineViewportStateCreateFlags* = distinct VkFlags - VkPipelineTessellationStateCreateFlags* = distinct VkFlags - VkPipelineInputAssemblyStateCreateFlags* = distinct VkFlags - VkPipelineVertexInputStateCreateFlags* = distinct VkFlags - VkPipelineShaderStageCreateFlags* = distinct VkFlags - VkDescriptorSetLayoutCreateFlags* = distinct VkFlags - VkBufferViewCreateFlags* = distinct VkFlags - VkInstanceCreateFlags* = distinct VkFlags - VkDeviceCreateFlags* = distinct VkFlags - VkDeviceQueueCreateFlags* = distinct VkFlags - VkQueueFlags* = distinct VkFlags - VkMemoryPropertyFlags* = distinct VkFlags - VkMemoryHeapFlags* = distinct VkFlags - VkAccessFlags* = distinct VkFlags - VkBufferUsageFlags* = distinct VkFlags - VkBufferCreateFlags* = distinct VkFlags - VkShaderStageFlags* = distinct VkFlags - VkImageUsageFlags* = distinct VkFlags - VkImageCreateFlags* = distinct VkFlags - VkImageViewCreateFlags* = distinct VkFlags - VkPipelineCreateFlags* = distinct VkFlags - VkColorComponentFlags* = distinct VkFlags - VkFenceCreateFlags* = distinct VkFlags - VkSemaphoreCreateFlags* = distinct VkFlags - VkFormatFeatureFlags* = distinct VkFlags - VkQueryControlFlags* = distinct VkFlags - VkQueryResultFlags* = distinct VkFlags - VkShaderModuleCreateFlags* = distinct VkFlags - VkEventCreateFlags* = distinct VkFlags - VkCommandPoolCreateFlags* = distinct VkFlags - VkCommandPoolResetFlags* = distinct VkFlags - VkCommandBufferResetFlags* = distinct VkFlags - VkCommandBufferUsageFlags* = distinct VkFlags - VkQueryPipelineStatisticFlags* = distinct VkFlags - VkMemoryMapFlags* = distinct VkFlags - VkImageAspectFlags* = distinct VkFlags - VkSparseMemoryBindFlags* = distinct VkFlags - VkSparseImageFormatFlags* = distinct VkFlags - VkSubpassDescriptionFlags* = distinct VkFlags - VkPipelineStageFlags* = distinct VkFlags - VkSampleCountFlags* = distinct VkFlags - VkAttachmentDescriptionFlags* = distinct VkFlags - VkStencilFaceFlags* = distinct VkFlags - VkCullModeFlags* = distinct VkFlags - VkDescriptorPoolCreateFlags* = distinct VkFlags - VkDescriptorPoolResetFlags* = distinct VkFlags - VkDependencyFlags* = distinct VkFlags - VkSubgroupFeatureFlags* = distinct VkFlags - VkIndirectCommandsLayoutUsageFlagsNV* = distinct VkFlags - VkIndirectStateFlagsNV* = distinct VkFlags - VkGeometryFlagsKHR* = distinct VkFlags - VkGeometryInstanceFlagsKHR* = distinct VkFlags - VkBuildAccelerationStructureFlagsKHR* = distinct VkFlags - VkPrivateDataSlotCreateFlags* = distinct VkFlags - VkAccelerationStructureCreateFlagsKHR* = distinct VkFlags - VkDescriptorUpdateTemplateCreateFlags* = distinct VkFlags - VkPipelineCreationFeedbackFlags* = distinct VkFlags - VkPerformanceCounterDescriptionFlagsKHR* = distinct VkFlags - VkAcquireProfilingLockFlagsKHR* = distinct VkFlags - VkSemaphoreWaitFlags* = distinct VkFlags - VkPipelineCompilerControlFlagsAMD* = distinct VkFlags - VkShaderCorePropertiesFlagsAMD* = distinct VkFlags - VkDeviceDiagnosticsConfigFlagsNV* = distinct VkFlags - VkRefreshObjectFlagsKHR* = distinct VkFlags - VkAccessFlags2* = distinct VkFlags - VkPipelineStageFlags2* = distinct VkFlags - VkAccelerationStructureMotionInfoFlagsNV* = distinct VkFlags - VkAccelerationStructureMotionInstanceFlagsNV* = distinct VkFlags - VkFormatFeatureFlags2* = distinct VkFlags - VkRenderingFlags* = distinct VkFlags - VkMemoryDecompressionMethodFlagsNV* = distinct VkFlags - VkBuildMicromapFlagsEXT* = distinct VkFlags - VkMicromapCreateFlagsEXT* = distinct VkFlags - VkDirectDriverLoadingFlagsLUNARG* = distinct VkFlags - VkCompositeAlphaFlagsKHR* = distinct VkFlags - VkDisplayPlaneAlphaFlagsKHR* = distinct VkFlags - VkSurfaceTransformFlagsKHR* = distinct VkFlags - VkSwapchainCreateFlagsKHR* = distinct VkFlags - VkDisplayModeCreateFlagsKHR* = distinct VkFlags - VkDisplaySurfaceCreateFlagsKHR* = distinct VkFlags - VkAndroidSurfaceCreateFlagsKHR* = distinct VkFlags - VkViSurfaceCreateFlagsNN* = distinct VkFlags - VkWaylandSurfaceCreateFlagsKHR* = distinct VkFlags - VkWin32SurfaceCreateFlagsKHR* = distinct VkFlags - VkXlibSurfaceCreateFlagsKHR* = distinct VkFlags - VkXcbSurfaceCreateFlagsKHR* = distinct VkFlags - VkDirectFBSurfaceCreateFlagsEXT* = distinct VkFlags - VkIOSSurfaceCreateFlagsMVK* = distinct VkFlags - VkMacOSSurfaceCreateFlagsMVK* = distinct VkFlags - VkMetalSurfaceCreateFlagsEXT* = distinct VkFlags - VkImagePipeSurfaceCreateFlagsFUCHSIA* = distinct VkFlags - VkStreamDescriptorSurfaceCreateFlagsGGP* = distinct VkFlags - VkHeadlessSurfaceCreateFlagsEXT* = distinct VkFlags - VkScreenSurfaceCreateFlagsQNX* = distinct VkFlags - VkPeerMemoryFeatureFlags* = distinct VkFlags - VkMemoryAllocateFlags* = distinct VkFlags - VkDeviceGroupPresentModeFlagsKHR* = distinct VkFlags - VkDebugReportFlagsEXT* = distinct VkFlags - VkCommandPoolTrimFlags* = distinct VkFlags - VkExternalMemoryHandleTypeFlagsNV* = distinct VkFlags - VkExternalMemoryFeatureFlagsNV* = distinct VkFlags - VkExternalMemoryHandleTypeFlags* = distinct VkFlags - VkExternalMemoryFeatureFlags* = distinct VkFlags - VkExternalSemaphoreHandleTypeFlags* = distinct VkFlags - VkExternalSemaphoreFeatureFlags* = distinct VkFlags - VkSemaphoreImportFlags* = distinct VkFlags - VkExternalFenceHandleTypeFlags* = distinct VkFlags - VkExternalFenceFeatureFlags* = distinct VkFlags - VkFenceImportFlags* = distinct VkFlags - VkSurfaceCounterFlagsEXT* = distinct VkFlags - VkPipelineViewportSwizzleStateCreateFlagsNV* = distinct VkFlags - VkPipelineDiscardRectangleStateCreateFlagsEXT* = distinct VkFlags - VkPipelineCoverageToColorStateCreateFlagsNV* = distinct VkFlags - VkPipelineCoverageModulationStateCreateFlagsNV* = distinct VkFlags - VkPipelineCoverageReductionStateCreateFlagsNV* = distinct VkFlags - VkValidationCacheCreateFlagsEXT* = distinct VkFlags - VkDebugUtilsMessageSeverityFlagsEXT* = distinct VkFlags - VkDebugUtilsMessageTypeFlagsEXT* = distinct VkFlags - VkDebugUtilsMessengerCreateFlagsEXT* = distinct VkFlags - VkDebugUtilsMessengerCallbackDataFlagsEXT* = distinct VkFlags - VkDeviceMemoryReportFlagsEXT* = distinct VkFlags - VkPipelineRasterizationConservativeStateCreateFlagsEXT* = distinct VkFlags - VkDescriptorBindingFlags* = distinct VkFlags - VkConditionalRenderingFlagsEXT* = distinct VkFlags - VkResolveModeFlags* = distinct VkFlags - VkPipelineRasterizationStateStreamCreateFlagsEXT* = distinct VkFlags - VkPipelineRasterizationDepthClipStateCreateFlagsEXT* = distinct VkFlags - VkSwapchainImageUsageFlagsANDROID* = distinct VkFlags - VkToolPurposeFlags* = distinct VkFlags - VkSubmitFlags* = distinct VkFlags - VkImageFormatConstraintsFlagsFUCHSIA* = distinct VkFlags - VkImageConstraintsInfoFlagsFUCHSIA* = distinct VkFlags - VkGraphicsPipelineLibraryFlagsEXT* = distinct VkFlags - VkImageCompressionFlagsEXT* = distinct VkFlags - VkImageCompressionFixedRateFlagsEXT* = distinct VkFlags - VkExportMetalObjectTypeFlagsEXT* = distinct VkFlags - VkDeviceAddressBindingFlagsEXT* = distinct VkFlags - VkOpticalFlowGridSizeFlagsNV* = distinct VkFlags - VkOpticalFlowUsageFlagsNV* = distinct VkFlags - VkOpticalFlowSessionCreateFlagsNV* = distinct VkFlags - VkOpticalFlowExecuteFlagsNV* = distinct VkFlags - VkPresentScalingFlagsEXT* = distinct VkFlags - VkPresentGravityFlagsEXT* = distinct VkFlags - VkVideoCodecOperationFlagsKHR* = distinct VkFlags - VkVideoCapabilityFlagsKHR* = distinct VkFlags - VkVideoSessionCreateFlagsKHR* = distinct VkFlags - VkVideoSessionParametersCreateFlagsKHR* = distinct VkFlags - VkVideoBeginCodingFlagsKHR* = distinct VkFlags - VkVideoEndCodingFlagsKHR* = distinct VkFlags - VkVideoCodingControlFlagsKHR* = distinct VkFlags - VkVideoDecodeUsageFlagsKHR* = distinct VkFlags - VkVideoDecodeCapabilityFlagsKHR* = distinct VkFlags - VkVideoDecodeFlagsKHR* = distinct VkFlags - VkVideoDecodeH264PictureLayoutFlagsKHR* = distinct VkFlags - VkVideoEncodeFlagsKHR* = distinct VkFlags - VkVideoEncodeUsageFlagsKHR* = distinct VkFlags - VkVideoEncodeContentFlagsKHR* = distinct VkFlags - VkVideoEncodeCapabilityFlagsKHR* = distinct VkFlags - VkVideoEncodeRateControlFlagsKHR* = distinct VkFlags - VkVideoEncodeRateControlModeFlagsKHR* = distinct VkFlags - VkVideoChromaSubsamplingFlagsKHR* = distinct VkFlags - VkVideoComponentBitDepthFlagsKHR* = distinct VkFlags - VkVideoEncodeH264CapabilityFlagsEXT* = distinct VkFlags - VkVideoEncodeH264InputModeFlagsEXT* = distinct VkFlags - VkVideoEncodeH264OutputModeFlagsEXT* = distinct VkFlags - VkVideoEncodeH265CapabilityFlagsEXT* = distinct VkFlags - VkVideoEncodeH265InputModeFlagsEXT* = distinct VkFlags - VkVideoEncodeH265OutputModeFlagsEXT* = distinct VkFlags - VkVideoEncodeH265CtbSizeFlagsEXT* = distinct VkFlags - VkVideoEncodeH265TransformBlockSizeFlagsEXT* = distinct VkFlags -let vkGetInstanceProcAddr = cast[proc(instance: VkInstance, name: cstring): pointer {.stdcall.}](checkedSymAddr(vulkanLib, "vkGetInstanceProcAddr")) -type - VkImageLayout* {.size: sizeof(cint).} = enum - VK_IMAGE_LAYOUT_UNDEFINED = 0 - VK_IMAGE_LAYOUT_GENERAL = 1 - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2 - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3 - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4 - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5 - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6 - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7 - VK_IMAGE_LAYOUT_PREINITIALIZED = 8 - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002 - VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR = 1000024000 - VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR = 1000024001 - VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR = 1000024002 - VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000 - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000 - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001 - VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR = 1000164003 - VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000 - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000 - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001 - VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002 - VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003 - VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR = 1000299000 - VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR = 1000299001 - VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR = 1000299002 - VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL = 1000314000 - VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL = 1000314001 - VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT = 1000339000 - VkAttachmentLoadOp* {.size: sizeof(cint).} = enum - VK_ATTACHMENT_LOAD_OP_LOAD = 0 - VK_ATTACHMENT_LOAD_OP_CLEAR = 1 - VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2 - VK_ATTACHMENT_LOAD_OP_NONE_EXT = 1000400000 - VkAttachmentStoreOp* {.size: sizeof(cint).} = enum - VK_ATTACHMENT_STORE_OP_STORE = 0 - VK_ATTACHMENT_STORE_OP_DONT_CARE = 1 - VK_ATTACHMENT_STORE_OP_NONE = 1000301000 - VkImageType* {.size: sizeof(cint).} = enum - VK_IMAGE_TYPE_1D = 0 - VK_IMAGE_TYPE_2D = 1 - VK_IMAGE_TYPE_3D = 2 - VkImageTiling* {.size: sizeof(cint).} = enum - VK_IMAGE_TILING_OPTIMAL = 0 - VK_IMAGE_TILING_LINEAR = 1 - VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT = 1000158000 - VkImageViewType* {.size: sizeof(cint).} = enum - VK_IMAGE_VIEW_TYPE_1D = 0 - VK_IMAGE_VIEW_TYPE_2D = 1 - VK_IMAGE_VIEW_TYPE_3D = 2 - VK_IMAGE_VIEW_TYPE_CUBE = 3 - VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4 - VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5 - VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6 - VkCommandBufferLevel* {.size: sizeof(cint).} = enum - VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0 - VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1 - VkComponentSwizzle* {.size: sizeof(cint).} = enum - VK_COMPONENT_SWIZZLE_IDENTITY = 0 - VK_COMPONENT_SWIZZLE_ZERO = 1 - VK_COMPONENT_SWIZZLE_ONE = 2 - VK_COMPONENT_SWIZZLE_R = 3 - VK_COMPONENT_SWIZZLE_G = 4 - VK_COMPONENT_SWIZZLE_B = 5 - VK_COMPONENT_SWIZZLE_A = 6 - VkDescriptorType* {.size: sizeof(cint).} = enum - VK_DESCRIPTOR_TYPE_SAMPLER = 0 - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1 - VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2 - VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3 - VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4 - VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5 - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6 - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7 - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8 - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9 - VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10 - VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000 - VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000 - VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000 - VK_DESCRIPTOR_TYPE_MUTABLE_EXT = 1000351000 - VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000 - VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001 - VkQueryType* {.size: sizeof(cint).} = enum - VK_QUERY_TYPE_OCCLUSION = 0 - VK_QUERY_TYPE_PIPELINE_STATISTICS = 1 - VK_QUERY_TYPE_TIMESTAMP = 2 - VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR = 1000023000 - VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004 - VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR = 1000116000 - VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000150000 - VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150001 - VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000 - VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000 - VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR = 1000299000 - VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT = 1000328000 - VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT = 1000382000 - VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR = 1000386000 - VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR = 1000386001 - VK_QUERY_TYPE_MICROMAP_SERIALIZATION_SIZE_EXT = 1000396000 - VK_QUERY_TYPE_MICROMAP_COMPACTED_SIZE_EXT = 1000396001 - VkBorderColor* {.size: sizeof(cint).} = enum - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0 - VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1 - VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2 - VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3 - VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4 - VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5 - VK_BORDER_COLOR_FLOAT_CUSTOM_EXT = 1000287003 - VK_BORDER_COLOR_INT_CUSTOM_EXT = 1000287004 - VkPipelineBindPoint* {.size: sizeof(cint).} = enum - VK_PIPELINE_BIND_POINT_GRAPHICS = 0 - VK_PIPELINE_BIND_POINT_COMPUTE = 1 - VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000 - VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI = 1000369003 - VkPipelineCacheHeaderVersion* {.size: sizeof(cint).} = enum - VK_PIPELINE_CACHE_HEADER_VERSION_ONE_ENUM = 1 - VK_PIPELINE_CACHE_HEADER_VERSION_SAFETY_CRITICAL_ONE_ENUM = 1000298001 - VkPipelineCacheCreateFlagBits* {.size: sizeof(cint).} = enum - VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0b00000000000000000000000000000001 - VK_PIPELINE_CACHE_CREATE_RESERVED_1_BIT_EXT = 0b00000000000000000000000000000010 - VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkPipelineCacheCreateFlagBits]): VkPipelineCacheCreateFlags = - for flag in flags: - result = VkPipelineCacheCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkPipelineCacheCreateFlags): seq[VkPipelineCacheCreateFlagBits] = - for value in VkPipelineCacheCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPipelineCacheCreateFlags): bool = cint(a) == cint(b) -type - VkPrimitiveTopology* {.size: sizeof(cint).} = enum - VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0 - VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1 - VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2 - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3 - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4 - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5 - VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6 - VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7 - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8 - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9 - VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10 - VkSharingMode* {.size: sizeof(cint).} = enum - VK_SHARING_MODE_EXCLUSIVE = 0 - VK_SHARING_MODE_CONCURRENT = 1 - VkIndexType* {.size: sizeof(cint).} = enum - VK_INDEX_TYPE_UINT16 = 0 - VK_INDEX_TYPE_UINT32 = 1 - VK_INDEX_TYPE_NONE_KHR = 1000165000 - VK_INDEX_TYPE_UINT8_EXT = 1000265000 - VkFilter* {.size: sizeof(cint).} = enum - VK_FILTER_NEAREST = 0 - VK_FILTER_LINEAR = 1 - VK_FILTER_CUBIC_EXT = 1000015000 - VkSamplerMipmapMode* {.size: sizeof(cint).} = enum - VK_SAMPLER_MIPMAP_MODE_NEAREST = 0 - VK_SAMPLER_MIPMAP_MODE_LINEAR = 1 - VkSamplerAddressMode* {.size: sizeof(cint).} = enum - VK_SAMPLER_ADDRESS_MODE_REPEAT = 0 - VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1 - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2 - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3 - VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4 - VkCompareOp* {.size: sizeof(cint).} = enum - VK_COMPARE_OP_NEVER = 0 - VK_COMPARE_OP_LESS = 1 - VK_COMPARE_OP_EQUAL = 2 - VK_COMPARE_OP_LESS_OR_EQUAL = 3 - VK_COMPARE_OP_GREATER = 4 - VK_COMPARE_OP_NOT_EQUAL = 5 - VK_COMPARE_OP_GREATER_OR_EQUAL = 6 - VK_COMPARE_OP_ALWAYS = 7 - VkPolygonMode* {.size: sizeof(cint).} = enum - VK_POLYGON_MODE_FILL = 0 - VK_POLYGON_MODE_LINE = 1 - VK_POLYGON_MODE_POINT = 2 - VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000 - VkFrontFace* {.size: sizeof(cint).} = enum - VK_FRONT_FACE_COUNTER_CLOCKWISE = 0 - VK_FRONT_FACE_CLOCKWISE = 1 - VkBlendFactor* {.size: sizeof(cint).} = enum - VK_BLEND_FACTOR_ZERO = 0 - VK_BLEND_FACTOR_ONE = 1 - VK_BLEND_FACTOR_SRC_COLOR = 2 - VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3 - VK_BLEND_FACTOR_DST_COLOR = 4 - VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5 - VK_BLEND_FACTOR_SRC_ALPHA = 6 - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7 - VK_BLEND_FACTOR_DST_ALPHA = 8 - VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9 - VK_BLEND_FACTOR_CONSTANT_COLOR = 10 - VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11 - VK_BLEND_FACTOR_CONSTANT_ALPHA = 12 - VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13 - VK_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14 - VK_BLEND_FACTOR_SRC1_COLOR = 15 - VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16 - VK_BLEND_FACTOR_SRC1_ALPHA = 17 - VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18 - VkBlendOp* {.size: sizeof(cint).} = enum - VK_BLEND_OP_ADD = 0 - VK_BLEND_OP_SUBTRACT = 1 - VK_BLEND_OP_REVERSE_SUBTRACT = 2 - VK_BLEND_OP_MIN = 3 - VK_BLEND_OP_MAX = 4 - VK_BLEND_OP_ZERO_EXT = 1000148000 - VK_BLEND_OP_SRC_EXT = 1000148001 - VK_BLEND_OP_DST_EXT = 1000148002 - VK_BLEND_OP_SRC_OVER_EXT = 1000148003 - VK_BLEND_OP_DST_OVER_EXT = 1000148004 - VK_BLEND_OP_SRC_IN_EXT = 1000148005 - VK_BLEND_OP_DST_IN_EXT = 1000148006 - VK_BLEND_OP_SRC_OUT_EXT = 1000148007 - VK_BLEND_OP_DST_OUT_EXT = 1000148008 - VK_BLEND_OP_SRC_ATOP_EXT = 1000148009 - VK_BLEND_OP_DST_ATOP_EXT = 1000148010 - VK_BLEND_OP_XOR_EXT = 1000148011 - VK_BLEND_OP_MULTIPLY_EXT = 1000148012 - VK_BLEND_OP_SCREEN_EXT = 1000148013 - VK_BLEND_OP_OVERLAY_EXT = 1000148014 - VK_BLEND_OP_DARKEN_EXT = 1000148015 - VK_BLEND_OP_LIGHTEN_EXT = 1000148016 - VK_BLEND_OP_COLORDODGE_EXT = 1000148017 - VK_BLEND_OP_COLORBURN_EXT = 1000148018 - VK_BLEND_OP_HARDLIGHT_EXT = 1000148019 - VK_BLEND_OP_SOFTLIGHT_EXT = 1000148020 - VK_BLEND_OP_DIFFERENCE_EXT = 1000148021 - VK_BLEND_OP_EXCLUSION_EXT = 1000148022 - VK_BLEND_OP_INVERT_EXT = 1000148023 - VK_BLEND_OP_INVERT_RGB_EXT = 1000148024 - VK_BLEND_OP_LINEARDODGE_EXT = 1000148025 - VK_BLEND_OP_LINEARBURN_EXT = 1000148026 - VK_BLEND_OP_VIVIDLIGHT_EXT = 1000148027 - VK_BLEND_OP_LINEARLIGHT_EXT = 1000148028 - VK_BLEND_OP_PINLIGHT_EXT = 1000148029 - VK_BLEND_OP_HARDMIX_EXT = 1000148030 - VK_BLEND_OP_HSL_HUE_EXT = 1000148031 - VK_BLEND_OP_HSL_SATURATION_EXT = 1000148032 - VK_BLEND_OP_HSL_COLOR_EXT = 1000148033 - VK_BLEND_OP_HSL_LUMINOSITY_EXT = 1000148034 - VK_BLEND_OP_PLUS_EXT = 1000148035 - VK_BLEND_OP_PLUS_CLAMPED_EXT = 1000148036 - VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT = 1000148037 - VK_BLEND_OP_PLUS_DARKER_EXT = 1000148038 - VK_BLEND_OP_MINUS_EXT = 1000148039 - VK_BLEND_OP_MINUS_CLAMPED_EXT = 1000148040 - VK_BLEND_OP_CONTRAST_EXT = 1000148041 - VK_BLEND_OP_INVERT_OVG_EXT = 1000148042 - VK_BLEND_OP_RED_EXT = 1000148043 - VK_BLEND_OP_GREEN_EXT = 1000148044 - VK_BLEND_OP_BLUE_EXT = 1000148045 - VkStencilOp* {.size: sizeof(cint).} = enum - VK_STENCIL_OP_KEEP = 0 - VK_STENCIL_OP_ZERO = 1 - VK_STENCIL_OP_REPLACE = 2 - VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3 - VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4 - VK_STENCIL_OP_INVERT = 5 - VK_STENCIL_OP_INCREMENT_AND_WRAP = 6 - VK_STENCIL_OP_DECREMENT_AND_WRAP = 7 - VkLogicOp* {.size: sizeof(cint).} = enum - VK_LOGIC_OP_CLEAR = 0 - VK_LOGIC_OP_AND = 1 - VK_LOGIC_OP_AND_REVERSE = 2 - VK_LOGIC_OP_COPY = 3 - VK_LOGIC_OP_AND_INVERTED = 4 - VK_LOGIC_OP_NO_OP = 5 - VK_LOGIC_OP_XOR = 6 - VK_LOGIC_OP_OR = 7 - VK_LOGIC_OP_NOR = 8 - VK_LOGIC_OP_EQUIVALENT = 9 - VK_LOGIC_OP_INVERT = 10 - VK_LOGIC_OP_OR_REVERSE = 11 - VK_LOGIC_OP_COPY_INVERTED = 12 - VK_LOGIC_OP_OR_INVERTED = 13 - VK_LOGIC_OP_NAND = 14 - VK_LOGIC_OP_SET = 15 - VkInternalAllocationType* {.size: sizeof(cint).} = enum - VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0 - VkSystemAllocationScope* {.size: sizeof(cint).} = enum - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0 - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1 - VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2 - VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3 - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4 - VkPhysicalDeviceType* {.size: sizeof(cint).} = enum - VK_PHYSICAL_DEVICE_TYPE_OTHER = 0 - VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1 - VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2 - VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3 - VK_PHYSICAL_DEVICE_TYPE_CPU = 4 - VkVertexInputRate* {.size: sizeof(cint).} = enum - VK_VERTEX_INPUT_RATE_VERTEX = 0 - VK_VERTEX_INPUT_RATE_INSTANCE = 1 - VkFormat* {.size: sizeof(cint).} = enum - VK_FORMAT_UNDEFINED = 0 - VK_FORMAT_R4G4_UNORM_PACK8 = 1 - VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2 - VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3 - VK_FORMAT_R5G6B5_UNORM_PACK16 = 4 - VK_FORMAT_B5G6R5_UNORM_PACK16 = 5 - VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6 - VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7 - VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8 - VK_FORMAT_R8_UNORM = 9 - VK_FORMAT_R8_SNORM = 10 - VK_FORMAT_R8_USCALED = 11 - VK_FORMAT_R8_SSCALED = 12 - VK_FORMAT_R8_UINT = 13 - VK_FORMAT_R8_SINT = 14 - VK_FORMAT_R8_SRGB = 15 - VK_FORMAT_R8G8_UNORM = 16 - VK_FORMAT_R8G8_SNORM = 17 - VK_FORMAT_R8G8_USCALED = 18 - VK_FORMAT_R8G8_SSCALED = 19 - VK_FORMAT_R8G8_UINT = 20 - VK_FORMAT_R8G8_SINT = 21 - VK_FORMAT_R8G8_SRGB = 22 - VK_FORMAT_R8G8B8_UNORM = 23 - VK_FORMAT_R8G8B8_SNORM = 24 - VK_FORMAT_R8G8B8_USCALED = 25 - VK_FORMAT_R8G8B8_SSCALED = 26 - VK_FORMAT_R8G8B8_UINT = 27 - VK_FORMAT_R8G8B8_SINT = 28 - VK_FORMAT_R8G8B8_SRGB = 29 - VK_FORMAT_B8G8R8_UNORM = 30 - VK_FORMAT_B8G8R8_SNORM = 31 - VK_FORMAT_B8G8R8_USCALED = 32 - VK_FORMAT_B8G8R8_SSCALED = 33 - VK_FORMAT_B8G8R8_UINT = 34 - VK_FORMAT_B8G8R8_SINT = 35 - VK_FORMAT_B8G8R8_SRGB = 36 - VK_FORMAT_R8G8B8A8_UNORM = 37 - VK_FORMAT_R8G8B8A8_SNORM = 38 - VK_FORMAT_R8G8B8A8_USCALED = 39 - VK_FORMAT_R8G8B8A8_SSCALED = 40 - VK_FORMAT_R8G8B8A8_UINT = 41 - VK_FORMAT_R8G8B8A8_SINT = 42 - VK_FORMAT_R8G8B8A8_SRGB = 43 - VK_FORMAT_B8G8R8A8_UNORM = 44 - VK_FORMAT_B8G8R8A8_SNORM = 45 - VK_FORMAT_B8G8R8A8_USCALED = 46 - VK_FORMAT_B8G8R8A8_SSCALED = 47 - VK_FORMAT_B8G8R8A8_UINT = 48 - VK_FORMAT_B8G8R8A8_SINT = 49 - VK_FORMAT_B8G8R8A8_SRGB = 50 - VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51 - VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52 - VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53 - VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54 - VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55 - VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56 - VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57 - VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58 - VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59 - VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60 - VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61 - VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62 - VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63 - VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64 - VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65 - VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66 - VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67 - VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68 - VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69 - VK_FORMAT_R16_UNORM = 70 - VK_FORMAT_R16_SNORM = 71 - VK_FORMAT_R16_USCALED = 72 - VK_FORMAT_R16_SSCALED = 73 - VK_FORMAT_R16_UINT = 74 - VK_FORMAT_R16_SINT = 75 - VK_FORMAT_R16_SFLOAT = 76 - VK_FORMAT_R16G16_UNORM = 77 - VK_FORMAT_R16G16_SNORM = 78 - VK_FORMAT_R16G16_USCALED = 79 - VK_FORMAT_R16G16_SSCALED = 80 - VK_FORMAT_R16G16_UINT = 81 - VK_FORMAT_R16G16_SINT = 82 - VK_FORMAT_R16G16_SFLOAT = 83 - VK_FORMAT_R16G16B16_UNORM = 84 - VK_FORMAT_R16G16B16_SNORM = 85 - VK_FORMAT_R16G16B16_USCALED = 86 - VK_FORMAT_R16G16B16_SSCALED = 87 - VK_FORMAT_R16G16B16_UINT = 88 - VK_FORMAT_R16G16B16_SINT = 89 - VK_FORMAT_R16G16B16_SFLOAT = 90 - VK_FORMAT_R16G16B16A16_UNORM = 91 - VK_FORMAT_R16G16B16A16_SNORM = 92 - VK_FORMAT_R16G16B16A16_USCALED = 93 - VK_FORMAT_R16G16B16A16_SSCALED = 94 - VK_FORMAT_R16G16B16A16_UINT = 95 - VK_FORMAT_R16G16B16A16_SINT = 96 - VK_FORMAT_R16G16B16A16_SFLOAT = 97 - VK_FORMAT_R32_UINT = 98 - VK_FORMAT_R32_SINT = 99 - VK_FORMAT_R32_SFLOAT = 100 - VK_FORMAT_R32G32_UINT = 101 - VK_FORMAT_R32G32_SINT = 102 - VK_FORMAT_R32G32_SFLOAT = 103 - VK_FORMAT_R32G32B32_UINT = 104 - VK_FORMAT_R32G32B32_SINT = 105 - VK_FORMAT_R32G32B32_SFLOAT = 106 - VK_FORMAT_R32G32B32A32_UINT = 107 - VK_FORMAT_R32G32B32A32_SINT = 108 - VK_FORMAT_R32G32B32A32_SFLOAT = 109 - VK_FORMAT_R64_UINT = 110 - VK_FORMAT_R64_SINT = 111 - VK_FORMAT_R64_SFLOAT = 112 - VK_FORMAT_R64G64_UINT = 113 - VK_FORMAT_R64G64_SINT = 114 - VK_FORMAT_R64G64_SFLOAT = 115 - VK_FORMAT_R64G64B64_UINT = 116 - VK_FORMAT_R64G64B64_SINT = 117 - VK_FORMAT_R64G64B64_SFLOAT = 118 - VK_FORMAT_R64G64B64A64_UINT = 119 - VK_FORMAT_R64G64B64A64_SINT = 120 - VK_FORMAT_R64G64B64A64_SFLOAT = 121 - VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122 - VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123 - VK_FORMAT_D16_UNORM = 124 - VK_FORMAT_X8_D24_UNORM_PACK32 = 125 - VK_FORMAT_D32_SFLOAT = 126 - VK_FORMAT_S8_UINT = 127 - VK_FORMAT_D16_UNORM_S8_UINT = 128 - VK_FORMAT_D24_UNORM_S8_UINT = 129 - VK_FORMAT_D32_SFLOAT_S8_UINT = 130 - VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131 - VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132 - VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133 - VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134 - VK_FORMAT_BC2_UNORM_BLOCK = 135 - VK_FORMAT_BC2_SRGB_BLOCK = 136 - VK_FORMAT_BC3_UNORM_BLOCK = 137 - VK_FORMAT_BC3_SRGB_BLOCK = 138 - VK_FORMAT_BC4_UNORM_BLOCK = 139 - VK_FORMAT_BC4_SNORM_BLOCK = 140 - VK_FORMAT_BC5_UNORM_BLOCK = 141 - VK_FORMAT_BC5_SNORM_BLOCK = 142 - VK_FORMAT_BC6H_UFLOAT_BLOCK = 143 - VK_FORMAT_BC6H_SFLOAT_BLOCK = 144 - VK_FORMAT_BC7_UNORM_BLOCK = 145 - VK_FORMAT_BC7_SRGB_BLOCK = 146 - VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147 - VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148 - VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149 - VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150 - VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151 - VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152 - VK_FORMAT_EAC_R11_UNORM_BLOCK = 153 - VK_FORMAT_EAC_R11_SNORM_BLOCK = 154 - VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155 - VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156 - VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157 - VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158 - VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159 - VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160 - VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161 - VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162 - VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163 - VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164 - VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165 - VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166 - VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167 - VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168 - VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169 - VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170 - VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171 - VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172 - VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173 - VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174 - VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175 - VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176 - VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177 - VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178 - VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179 - VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180 - VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181 - VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182 - VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183 - VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184 - VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000 - VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001 - VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002 - VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003 - VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004 - VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005 - VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006 - VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007 - VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK = 1000066000 - VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK = 1000066001 - VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK = 1000066002 - VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK = 1000066003 - VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK = 1000066004 - VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK = 1000066005 - VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK = 1000066006 - VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK = 1000066007 - VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK = 1000066008 - VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK = 1000066009 - VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK = 1000066010 - VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK = 1000066011 - VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK = 1000066012 - VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK = 1000066013 - VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000 - VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001 - VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002 - VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003 - VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004 - VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005 - VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006 - VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007 - VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008 - VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009 - VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010 - VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011 - VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012 - VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013 - VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014 - VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015 - VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016 - VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017 - VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018 - VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019 - VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020 - VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021 - VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022 - VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023 - VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024 - VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025 - VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026 - VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027 - VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028 - VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029 - VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030 - VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031 - VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032 - VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033 - VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT = 1000288000 - VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT = 1000288001 - VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT = 1000288002 - VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT = 1000288003 - VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT = 1000288004 - VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT = 1000288005 - VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT = 1000288006 - VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT = 1000288007 - VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT = 1000288008 - VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT = 1000288009 - VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT = 1000288010 - VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT = 1000288011 - VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT = 1000288012 - VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT = 1000288013 - VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT = 1000288014 - VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT = 1000288015 - VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT = 1000288016 - VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT = 1000288017 - VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT = 1000288018 - VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT = 1000288019 - VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT = 1000288020 - VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT = 1000288021 - VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT = 1000288022 - VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT = 1000288023 - VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT = 1000288024 - VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT = 1000288025 - VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT = 1000288026 - VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT = 1000288027 - VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT = 1000288028 - VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT = 1000288029 - VK_FORMAT_G8_B8R8_2PLANE_444_UNORM = 1000330000 - VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16 = 1000330001 - VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16 = 1000330002 - VK_FORMAT_G16_B16R16_2PLANE_444_UNORM = 1000330003 - VK_FORMAT_A4R4G4B4_UNORM_PACK16 = 1000340000 - VK_FORMAT_A4B4G4R4_UNORM_PACK16 = 1000340001 - VK_FORMAT_R16G16_S10_5_NV = 1000464000 - VkStructureType* {.size: sizeof(cint).} = enum - VK_STRUCTURE_TYPE_APPLICATION_INFO = 0 - VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1 - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO = 2 - VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 3 - VK_STRUCTURE_TYPE_SUBMIT_INFO = 4 - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 5 - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE = 6 - VK_STRUCTURE_TYPE_BIND_SPARSE_INFO = 7 - VK_STRUCTURE_TYPE_FENCE_CREATE_INFO = 8 - VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO = 9 - VK_STRUCTURE_TYPE_EVENT_CREATE_INFO = 10 - VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO = 11 - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 12 - VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO = 13 - VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 14 - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO = 15 - VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO = 16 - VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO = 17 - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO = 18 - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19 - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20 - VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21 - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22 - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23 - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24 - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25 - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26 - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27 - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO = 28 - VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO = 29 - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO = 30 - VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO = 31 - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32 - VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO = 33 - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO = 34 - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET = 35 - VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET = 36 - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO = 37 - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO = 38 - VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO = 39 - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO = 40 - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO = 41 - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO = 42 - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO = 43 - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER = 44 - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 45 - VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46 - VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47 - VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES = 50 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES = 51 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES = 52 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES = 53 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES = 54 - VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000 - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001 - VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000 - VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001 - VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR = 1000003000 - VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000 - VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000 - VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000 - VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000 - VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000 - VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID = 1000010000 - VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID = 1000010001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID = 1000010002 - VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000 - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000 - VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000 - VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001 - VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002 - VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR = 1000023000 - VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR = 1000023001 - VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR = 1000023002 - VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR = 1000023003 - VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR = 1000023004 - VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR = 1000023005 - VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000023006 - VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR = 1000023007 - VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR = 1000023008 - VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR = 1000023009 - VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR = 1000023010 - VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR = 1000023011 - VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR = 1000023012 - VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR = 1000023013 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR = 1000023014 - VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR = 1000023015 - VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR = 1000023016 - VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR = 1000024000 - VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR = 1000024001 - VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR = 1000024002 - VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000 - VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001 - VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001 - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002 - VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX = 1000029000 - VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX = 1000029001 - VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX = 1000029002 - VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000 - VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT = 1000038000 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000038001 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000038002 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT = 1000038003 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT = 1000038004 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT = 1000038005 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT = 1000038006 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT = 1000038007 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT = 1000038008 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT = 1000038009 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT = 1000038010 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT = 1000039000 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000039001 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000039002 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT = 1000039003 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT = 1000039004 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT = 1000039005 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT = 1000039006 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT = 1000039007 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT = 1000039008 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT = 1000039009 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT = 1000039010 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR = 1000040000 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR = 1000040001 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR = 1000040003 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000040004 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR = 1000040005 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR = 1000040006 - VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000 - VK_STRUCTURE_TYPE_RENDERING_INFO = 1000044000 - VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO = 1000044001 - VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO = 1000044002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES = 1000044003 - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO = 1000044004 - VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006 - VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007 - VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008 - VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009 - VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000 - VK_STRUCTURE_TYPE_PRIVATE_VENDOR_INFO_RESERVED_OFFSET_0_NV = 1000051000 - VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002 - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000 - VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001 - VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000 - VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001 - VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 = 1000059000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001 - VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 = 1000059002 - VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 = 1000059003 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004 - VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 = 1000059005 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006 - VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008 - VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO = 1000060000 - VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003 - VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004 - VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO = 1000060005 - VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006 - VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007 - VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR = 1000060008 - VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR = 1000060009 - VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR = 1000060010 - VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011 - VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012 - VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013 - VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014 - VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000 - VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000 - VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001 - VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT = 1000068000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT = 1000068001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT = 1000068002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000 - VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000 - VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002 - VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES = 1000071003 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004 - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO = 1000072000 - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO = 1000072001 - VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO = 1000072002 - VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000 - VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001 - VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002 - VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR = 1000073003 - VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR = 1000074000 - VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR = 1000074001 - VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR = 1000074002 - VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR = 1000075000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000 - VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001 - VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO = 1000077000 - VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000 - VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001 - VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002 - VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR = 1000078003 - VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000 - VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR = 1000079001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000 - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001 - VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000 - VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000 - VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000 - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000 - VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000 - VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000 - VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT = 1000091001 - VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT = 1000091002 - VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003 - VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000 - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000 - VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000 - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT = 1000102000 - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT = 1000102001 - VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000 - VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001 - VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002 - VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003 - VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 = 1000109000 - VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2 = 1000109001 - VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2 = 1000109002 - VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 = 1000109003 - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2 = 1000109004 - VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO = 1000109005 - VK_STRUCTURE_TYPE_SUBPASS_END_INFO = 1000109006 - VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000 - VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES = 1000112001 - VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO = 1000113000 - VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000 - VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001 - VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002 - VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR = 1000115000 - VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR = 1000115001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR = 1000116000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR = 1000116001 - VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR = 1000116002 - VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR = 1000116003 - VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR = 1000116004 - VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR = 1000116005 - VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR = 1000116006 - VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_RESERVATION_INFO_KHR = 1000116007 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000 - VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001 - VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002 - VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000 - VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001 - VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000 - VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR = 1000121000 - VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR = 1000121001 - VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR = 1000121002 - VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR = 1000121003 - VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR = 1000121004 - VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000 - VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000 - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000 - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001 - VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000 - VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT = 1000128001 - VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT = 1000128002 - VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000128003 - VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004 - VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID = 1000129000 - VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID = 1000129001 - VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID = 1000129002 - VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003 - VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004 - VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005 - VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID = 1000129006 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000 - VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES = 1000138000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES = 1000138001 - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK = 1000138002 - VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO = 1000138003 - VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000 - VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001 - VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003 - VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT = 1000143004 - VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO = 1000145000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002 - VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 = 1000145003 - VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 = 1000146000 - VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 = 1000146001 - VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 = 1000146002 - VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 = 1000146003 - VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 = 1000146004 - VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001 - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002 - VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR = 1000150000 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR = 1000150002 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR = 1000150003 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR = 1000150004 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR = 1000150005 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR = 1000150006 - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000150007 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR = 1000150009 - VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR = 1000150010 - VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR = 1000150011 - VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR = 1000150012 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR = 1000150013 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR = 1000150014 - VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015 - VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017 - VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR = 1000150020 - VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001 - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000 - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO = 1000156001 - VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002 - VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004 - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005 - VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO = 1000157000 - VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO = 1000157001 - VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT = 1000158000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT = 1000158002 - VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003 - VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004 - VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005 - VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT = 1000158006 - VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000 - VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001 - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002 - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003 - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR = 1000163000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR = 1000163001 - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002 - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005 - VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001 - VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003 - VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004 - VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005 - VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006 - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009 - VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV = 1000165012 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000 - VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000 - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT = 1000170000 - VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT = 1000170001 - VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR = 1000174000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000 - VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000 - VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR = 1000181000 - VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD = 1000183000 - VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT = 1000184000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR = 1000187000 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000187001 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR = 1000187002 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR = 1000187003 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR = 1000187004 - VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR = 1000187005 - VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000 - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002 - VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP = 1000191000 - VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000 - VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR = 1000203000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000 - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002 - VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000 - VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES = 1000207000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES = 1000207001 - VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO = 1000207002 - VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO = 1000207003 - VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO = 1000207004 - VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO = 1000207005 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL = 1000209000 - VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL = 1000210000 - VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL = 1000210001 - VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL = 1000210002 - VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL = 1000210003 - VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL = 1000210004 - VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL = 1000210005 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000 - VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD = 1000213000 - VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD = 1000213001 - VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000 - VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001 - VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES = 1000225000 - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO = 1000225001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES = 1000225002 - VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000226000 - VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR = 1000226001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR = 1000226002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR = 1000226003 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR = 1000226004 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD = 1000227000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD = 1000229000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT = 1000234000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT = 1000237000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT = 1000238000 - VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT = 1000238001 - VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR = 1000239000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV = 1000240000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000 - VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001 - VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT = 1000244000 - VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO = 1000244001 - VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT = 1000244002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES = 1000245000 - VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000 - VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT = 1000247000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR = 1000248000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV = 1000249000 - VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV = 1000250000 - VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV = 1000250001 - VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV = 1000250002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT = 1000251000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT = 1000252000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT = 1000254000 - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT = 1000254001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT = 1000254002 - VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT = 1000255000 - VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT = 1000255001 - VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT = 1000255002 - VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES = 1000257000 - VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002 - VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003 - VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT = 1000259000 - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = 1000259001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = 1000259002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT = 1000260000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = 1000265000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT = 1000267000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000 - VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR = 1000269001 - VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002 - VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR = 1000269003 - VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004 - VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000 - VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT = 1000274000 - VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = 1000274001 - VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT = 1000274002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT = 1000275000 - VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT = 1000275001 - VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT = 1000275002 - VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT = 1000275003 - VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT = 1000275004 - VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT = 1000275005 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000 - VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001 - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002 - VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV = 1000277003 - VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV = 1000277004 - VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV = 1000277005 - VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV = 1000277006 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV = 1000277007 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV = 1000278000 - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV = 1000278001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES = 1000280000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES = 1000280001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES = 1000281001 - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000 - VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000 - VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001 - VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = 1000286000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = 1000286001 - VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002 - VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV = 1000292000 - VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_BARRIER_NV = 1000292001 - VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_BARRIER_CREATE_INFO_NV = 1000292002 - VK_STRUCTURE_TYPE_PRESENT_ID_KHR = 1000294000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR = 1000294001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES = 1000295000 - VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO = 1000295001 - VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO = 1000295002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_SC_1_0_FEATURES = 1000298000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_SC_1_0_PROPERTIES = 1000298001 - VK_STRUCTURE_TYPE_DEVICE_OBJECT_RESERVATION_CREATE_INFO = 1000298002 - VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_RESERVATION_CREATE_INFO = 1000298003 - VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_CONSUMPTION = 1000298004 - VK_STRUCTURE_TYPE_PIPELINE_POOL_SIZE = 1000298005 - VK_STRUCTURE_TYPE_FAULT_DATA = 1000298007 - VK_STRUCTURE_TYPE_FAULT_CALLBACK_INFO = 1000298008 - VK_STRUCTURE_TYPE_PIPELINE_OFFLINE_CREATE_INFO = 1000298010 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR = 1000299000 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR = 1000299001 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR = 1000299002 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR = 1000299003 - VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR = 1000299004 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000 - VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001 - VK_STRUCTURE_TYPE_REFRESH_OBJECT_LIST_KHR = 1000308000 - VK_STRUCTURE_TYPE_RESERVED_QCOM = 1000309000 - VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT = 1000311000 - VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT = 1000311001 - VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT = 1000311002 - VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT = 1000311003 - VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT = 1000311004 - VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT = 1000311005 - VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT = 1000311006 - VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT = 1000311007 - VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT = 1000311008 - VK_STRUCTURE_TYPE_IMPORT_METAL_IO_SURFACE_INFO_EXT = 1000311009 - VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311010 - VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311011 - VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 = 1000314000 - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 = 1000314001 - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 = 1000314002 - VK_STRUCTURE_TYPE_DEPENDENCY_INFO = 1000314003 - VK_STRUCTURE_TYPE_SUBMIT_INFO_2 = 1000314004 - VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO = 1000314005 - VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO = 1000314006 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES = 1000314007 - VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008 - VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV = 1000314009 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT = 1000316000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_DENSITY_MAP_PROPERTIES_EXT = 1000316001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT = 1000316002 - VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT = 1000316003 - VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT = 1000316004 - VK_STRUCTURE_TYPE_BUFFER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316005 - VK_STRUCTURE_TYPE_IMAGE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316006 - VK_STRUCTURE_TYPE_IMAGE_VIEW_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316007 - VK_STRUCTURE_TYPE_SAMPLER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316008 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316009 - VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT = 1000316010 - VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT = 1000316011 - VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_PUSH_DESCRIPTOR_BUFFER_HANDLE_EXT = 1000316012 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT = 1000320000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT = 1000320001 - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT = 1000320002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD = 1000321000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR = 1000322000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR = 1000323000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV = 1000326000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV = 1000326001 - VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV = 1000326002 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV = 1000327000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV = 1000327001 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV = 1000327002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT = 1000328000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT = 1000328001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT = 1000330000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT = 1000332000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT = 1000332001 - VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM = 1000333000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000 - VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 = 1000337000 - VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2 = 1000337001 - VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2 = 1000337002 - VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2 = 1000337003 - VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2 = 1000337004 - VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2 = 1000337005 - VK_STRUCTURE_TYPE_BUFFER_COPY_2 = 1000337006 - VK_STRUCTURE_TYPE_IMAGE_COPY_2 = 1000337007 - VK_STRUCTURE_TYPE_IMAGE_BLIT_2 = 1000337008 - VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2 = 1000337009 - VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2 = 1000337010 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT = 1000338000 - VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT = 1000338001 - VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT = 1000338002 - VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT = 1000338003 - VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT = 1000338004 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT = 1000339000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT = 1000341000 - VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT = 1000341001 - VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT = 1000341002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT = 1000342000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT = 1000344000 - VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR = 1000347000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR = 1000347001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR = 1000348013 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT = 1000351000 - VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT = 1000351002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT = 1000352000 - VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT = 1000352001 - VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT = 1000352002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT = 1000353000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ADDRESS_BINDING_REPORT_FEATURES_EXT = 1000354000 - VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT = 1000354001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT = 1000355000 - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT = 1000355001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT = 1000356000 - VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 = 1000360000 - VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364000 - VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA = 1000364001 - VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364002 - VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365000 - VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365001 - VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA = 1000366000 - VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA = 1000366001 - VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA = 1000366002 - VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA = 1000366003 - VK_STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA = 1000366004 - VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA = 1000366005 - VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA = 1000366006 - VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA = 1000366007 - VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA = 1000366008 - VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA = 1000366009 - VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI = 1000369000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI = 1000369001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI = 1000369002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI = 1000370000 - VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV = 1000371000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV = 1000371001 - VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT = 1000372000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT = 1000372001 - VK_STRUCTURE_TYPE_IMPORT_FENCE_SCI_SYNC_INFO_NV = 1000373000 - VK_STRUCTURE_TYPE_EXPORT_FENCE_SCI_SYNC_INFO_NV = 1000373001 - VK_STRUCTURE_TYPE_FENCE_GET_SCI_SYNC_INFO_NV = 1000373002 - VK_STRUCTURE_TYPE_SCI_SYNC_ATTRIBUTES_INFO_NV = 1000373003 - VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_SCI_SYNC_INFO_NV = 1000373004 - VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_SCI_SYNC_INFO_NV = 1000373005 - VK_STRUCTURE_TYPE_SEMAPHORE_GET_SCI_SYNC_INFO_NV = 1000373006 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SCI_SYNC_FEATURES_NV = 1000373007 - VK_STRUCTURE_TYPE_IMPORT_MEMORY_SCI_BUF_INFO_NV = 1000374000 - VK_STRUCTURE_TYPE_EXPORT_MEMORY_SCI_BUF_INFO_NV = 1000374001 - VK_STRUCTURE_TYPE_MEMORY_GET_SCI_BUF_INFO_NV = 1000374002 - VK_STRUCTURE_TYPE_MEMORY_SCI_BUF_PROPERTIES_NV = 1000374003 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCI_BUF_FEATURES_NV = 1000374004 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT = 1000376000 - VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT = 1000376001 - VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT = 1000376002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT = 1000377000 - VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX = 1000378000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT = 1000381000 - VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT = 1000381001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT = 1000382000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR = 1000386000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR = 1000388000 - VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR = 1000388001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT = 1000391000 - VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT = 1000391001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT = 1000393000 - VK_STRUCTURE_TYPE_MICROMAP_BUILD_INFO_EXT = 1000396000 - VK_STRUCTURE_TYPE_MICROMAP_VERSION_INFO_EXT = 1000396001 - VK_STRUCTURE_TYPE_COPY_MICROMAP_INFO_EXT = 1000396002 - VK_STRUCTURE_TYPE_COPY_MICROMAP_TO_MEMORY_INFO_EXT = 1000396003 - VK_STRUCTURE_TYPE_COPY_MEMORY_TO_MICROMAP_INFO_EXT = 1000396004 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_EXT = 1000396005 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT = 1000396006 - VK_STRUCTURE_TYPE_MICROMAP_CREATE_INFO_EXT = 1000396007 - VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT = 1000396008 - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT = 1000396009 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI = 1000404000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI = 1000404001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000 - VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES = 1000413000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 1000413001 - VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS = 1000413002 - VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS = 1000413003 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM = 1000415000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT = 1000418000 - VK_STRUCTURE_TYPE_IMAGE_VIEW_SLICED_CREATE_INFO_EXT = 1000418001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000 - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001 - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = 1000421000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT = 1000422000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM = 1000425000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM = 1000425001 - VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM = 1000425002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV = 1000426000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV = 1000426001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV = 1000427000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV = 1000427001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV = 1000430000 - VK_STRUCTURE_TYPE_APPLICATION_PARAMETERS_EXT = 1000435000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT = 1000437000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM = 1000440000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM = 1000440001 - VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM = 1000440002 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT = 1000455000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT = 1000455001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT = 1000458000 - VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT = 1000458001 - VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000458002 - VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT = 1000458003 - VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG = 1000459000 - VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG = 1000459001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT = 1000462000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT = 1000462001 - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT = 1000462002 - VK_STRUCTURE_TYPE_SHADER_MODULE_IDENTIFIER_EXT = 1000462003 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV = 1000464000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV = 1000464001 - VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV = 1000464002 - VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV = 1000464003 - VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_INFO_NV = 1000464004 - VK_STRUCTURE_TYPE_OPTICAL_FLOW_EXECUTE_INFO_NV = 1000464005 - VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV = 1000464010 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT = 1000465000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = 1000466000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM = 1000484000 - VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM = 1000484001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC = 1000485000 - VK_STRUCTURE_TYPE_AMIGO_PROFILING_SUBMIT_INFO_SEC = 1000485001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM = 1000488000 - VK_STRUCTURE_TYPE_SEMAPHORE_SCI_SYNC_POOL_CREATE_INFO_NV = 1000489000 - VK_STRUCTURE_TYPE_SEMAPHORE_SCI_SYNC_CREATE_INFO_NV = 1000489001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SCI_SYNC_2_FEATURES_NV = 1000489002 - VK_STRUCTURE_TYPE_DEVICE_SEMAPHORE_SCI_SYNC_POOL_RESERVATION_CREATE_INFO_NV = 1000489003 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV = 1000490000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV = 1000490001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM = 1000497000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM = 1000497001 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT = 1000498000 - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM = 1000510000 - VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM = 1000510001 - VkSubpassContents* {.size: sizeof(cint).} = enum - VK_SUBPASS_CONTENTS_INLINE = 0 - VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1 - VkResult* {.size: sizeof(cint).} = enum - VK_ERROR_COMPRESSION_EXHAUSTED_EXT = -1000338000 - VK_ERROR_NO_PIPELINE_MATCH = -1000298001 - VK_ERROR_INVALID_PIPELINE_CACHE_DATA = -1000298000 - VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000 - VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000 - VK_ERROR_NOT_PERMITTED_KHR = -1000174001 - VK_ERROR_FRAGMENTATION = -1000161000 - VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000 - VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003 - VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000 - VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR = -1000023005 - VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR = -1000023004 - VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR = -1000023003 - VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR = -1000023002 - VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR = -1000023001 - VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR = -1000023000 - VK_ERROR_INVALID_SHADER_NV = -1000012000 - VK_ERROR_VALIDATION_FAILED_EXT = -1000011001 - VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001 - VK_ERROR_OUT_OF_DATE_KHR = -1000001004 - VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001 - VK_ERROR_SURFACE_LOST_KHR = -1000000000 - VK_ERROR_UNKNOWN = -13 - VK_ERROR_FRAGMENTED_POOL = -12 - VK_ERROR_FORMAT_NOT_SUPPORTED = -11 - VK_ERROR_TOO_MANY_OBJECTS = -10 - VK_ERROR_INCOMPATIBLE_DRIVER = -9 - VK_ERROR_FEATURE_NOT_PRESENT = -8 - VK_ERROR_EXTENSION_NOT_PRESENT = -7 - VK_ERROR_LAYER_NOT_PRESENT = -6 - VK_ERROR_MEMORY_MAP_FAILED = -5 - VK_ERROR_DEVICE_LOST = -4 - VK_ERROR_INITIALIZATION_FAILED = -3 - VK_ERROR_OUT_OF_DEVICE_MEMORY = -2 - VK_ERROR_OUT_OF_HOST_MEMORY = -1 - VK_SUCCESS = 0 - VK_NOT_READY = 1 - VK_TIMEOUT = 2 - VK_EVENT_SET = 3 - VK_EVENT_RESET = 4 - VK_INCOMPLETE = 5 - VK_SUBOPTIMAL_KHR = 1000001003 - VK_THREAD_IDLE_KHR = 1000268000 - VK_THREAD_DONE_KHR = 1000268001 - VK_OPERATION_DEFERRED_KHR = 1000268002 - VK_OPERATION_NOT_DEFERRED_KHR = 1000268003 - VK_PIPELINE_COMPILE_REQUIRED = 1000297000 - VkDynamicState* {.size: sizeof(cint).} = enum - VK_DYNAMIC_STATE_VIEWPORT = 0 - VK_DYNAMIC_STATE_SCISSOR = 1 - VK_DYNAMIC_STATE_LINE_WIDTH = 2 - VK_DYNAMIC_STATE_DEPTH_BIAS = 3 - VK_DYNAMIC_STATE_BLEND_CONSTANTS = 4 - VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5 - VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6 - VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7 - VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8 - VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000 - VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000 - VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT = 1000099001 - VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT = 1000099002 - VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000 - VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004 - VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006 - VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV = 1000205000 - VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001 - VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR = 1000226000 - VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000 - VK_DYNAMIC_STATE_CULL_MODE = 1000267000 - VK_DYNAMIC_STATE_FRONT_FACE = 1000267001 - VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY = 1000267002 - VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT = 1000267003 - VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT = 1000267004 - VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE = 1000267005 - VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE = 1000267006 - VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE = 1000267007 - VK_DYNAMIC_STATE_DEPTH_COMPARE_OP = 1000267008 - VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE = 1000267009 - VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE = 1000267010 - VK_DYNAMIC_STATE_STENCIL_OP = 1000267011 - VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR = 1000347000 - VK_DYNAMIC_STATE_VERTEX_INPUT_EXT = 1000352000 - VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT = 1000377000 - VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE = 1000377001 - VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE = 1000377002 - VK_DYNAMIC_STATE_LOGIC_OP_EXT = 1000377003 - VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE = 1000377004 - VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT = 1000381000 - VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT = 1000455002 - VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT = 1000455003 - VK_DYNAMIC_STATE_POLYGON_MODE_EXT = 1000455004 - VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT = 1000455005 - VK_DYNAMIC_STATE_SAMPLE_MASK_EXT = 1000455006 - VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT = 1000455007 - VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT = 1000455008 - VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT = 1000455009 - VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT = 1000455010 - VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT = 1000455011 - VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT = 1000455012 - VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT = 1000455013 - VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT = 1000455014 - VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT = 1000455015 - VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT = 1000455016 - VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT = 1000455017 - VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT = 1000455018 - VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT = 1000455019 - VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT = 1000455020 - VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT = 1000455021 - VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT = 1000455022 - VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV = 1000455023 - VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV = 1000455024 - VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV = 1000455025 - VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV = 1000455026 - VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV = 1000455027 - VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV = 1000455028 - VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV = 1000455029 - VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV = 1000455030 - VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV = 1000455031 - VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV = 1000455032 - VkDescriptorUpdateTemplateType* {.size: sizeof(cint).} = enum - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0 - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1 - VkObjectType* {.size: sizeof(cint).} = enum - VK_OBJECT_TYPE_UNKNOWN = 0 - VK_OBJECT_TYPE_INSTANCE = 1 - VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2 - VK_OBJECT_TYPE_DEVICE = 3 - VK_OBJECT_TYPE_QUEUE = 4 - VK_OBJECT_TYPE_SEMAPHORE = 5 - VK_OBJECT_TYPE_COMMAND_BUFFER = 6 - VK_OBJECT_TYPE_FENCE = 7 - VK_OBJECT_TYPE_DEVICE_MEMORY = 8 - VK_OBJECT_TYPE_BUFFER = 9 - VK_OBJECT_TYPE_IMAGE = 10 - VK_OBJECT_TYPE_EVENT = 11 - VK_OBJECT_TYPE_QUERY_POOL = 12 - VK_OBJECT_TYPE_BUFFER_VIEW = 13 - VK_OBJECT_TYPE_IMAGE_VIEW = 14 - VK_OBJECT_TYPE_SHADER_MODULE = 15 - VK_OBJECT_TYPE_PIPELINE_CACHE = 16 - VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17 - VK_OBJECT_TYPE_RENDER_PASS = 18 - VK_OBJECT_TYPE_PIPELINE = 19 - VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20 - VK_OBJECT_TYPE_SAMPLER = 21 - VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22 - VK_OBJECT_TYPE_DESCRIPTOR_SET = 23 - VK_OBJECT_TYPE_FRAMEBUFFER = 24 - VK_OBJECT_TYPE_COMMAND_POOL = 25 - VK_OBJECT_TYPE_SURFACE_KHR = 1000000000 - VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000 - VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000 - VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001 - VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000 - VK_OBJECT_TYPE_VIDEO_SESSION_KHR = 1000023000 - VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR = 1000023001 - VK_OBJECT_TYPE_CU_MODULE_NVX = 1000029000 - VK_OBJECT_TYPE_CU_FUNCTION_NVX = 1000029001 - VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000 - VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000 - VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000 - VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000 - VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000 - VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000 - VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000 - VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR = 1000268000 - VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV = 1000277000 - VK_OBJECT_TYPE_PRIVATE_DATA_SLOT = 1000295000 - VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = 1000366000 - VK_OBJECT_TYPE_MICROMAP_EXT = 1000396000 - VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV = 1000464000 - VK_OBJECT_TYPE_SEMAPHORE_SCI_SYNC_POOL_NV = 1000489000 - VkRayTracingInvocationReorderModeNV* {.size: sizeof(cint).} = enum - VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_NV = 0 - VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_NV = 1 - VkDirectDriverLoadingModeLUNARG* {.size: sizeof(cint).} = enum - VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG = 0 - VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG = 1 - VkQueueFlagBits* {.size: sizeof(cint).} = enum - VK_QUEUE_GRAPHICS_BIT = 0b00000000000000000000000000000001 - VK_QUEUE_COMPUTE_BIT = 0b00000000000000000000000000000010 - VK_QUEUE_TRANSFER_BIT = 0b00000000000000000000000000000100 - VK_QUEUE_SPARSE_BINDING_BIT = 0b00000000000000000000000000001000 - VK_QUEUE_PROTECTED_BIT = 0b00000000000000000000000000010000 - VK_QUEUE_VIDEO_DECODE_BIT_KHR = 0b00000000000000000000000000100000 - VK_QUEUE_VIDEO_ENCODE_BIT_KHR = 0b00000000000000000000000001000000 - VK_QUEUE_RESERVED_7_BIT_QCOM = 0b00000000000000000000000010000000 - VK_QUEUE_OPTICAL_FLOW_BIT_NV = 0b00000000000000000000000100000000 - VK_QUEUE_RESERVED_9_BIT_EXT = 0b00000000000000000000001000000000 -func toBits*(flags: openArray[VkQueueFlagBits]): VkQueueFlags = - for flag in flags: - result = VkQueueFlags(uint(result) or uint(flag)) -func toEnums*(number: VkQueueFlags): seq[VkQueueFlagBits] = - for value in VkQueueFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkQueueFlags): bool = cint(a) == cint(b) -type - VkCullModeFlagBits* {.size: sizeof(cint).} = enum - VK_CULL_MODE_FRONT_BIT = 0b00000000000000000000000000000001 - VK_CULL_MODE_BACK_BIT = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkCullModeFlagBits]): VkCullModeFlags = - for flag in flags: - result = VkCullModeFlags(uint(result) or uint(flag)) -func toEnums*(number: VkCullModeFlags): seq[VkCullModeFlagBits] = - for value in VkCullModeFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkCullModeFlags): bool = cint(a) == cint(b) -const - VK_CULL_MODE_NONE* = 0 - VK_CULL_MODE_FRONT_AND_BACK* = 0x00000003 -type - VkRenderPassCreateFlagBits* {.size: sizeof(cint).} = enum - VK_RENDER_PASS_CREATE_RESERVED_0_BIT_KHR = 0b00000000000000000000000000000001 - VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkRenderPassCreateFlagBits]): VkRenderPassCreateFlags = - for flag in flags: - result = VkRenderPassCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkRenderPassCreateFlags): seq[VkRenderPassCreateFlagBits] = - for value in VkRenderPassCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkRenderPassCreateFlags): bool = cint(a) == cint(b) -type - VkDeviceQueueCreateFlagBits* {.size: sizeof(cint).} = enum - VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 0b00000000000000000000000000000001 - VK_DEVICE_QUEUE_CREATE_RESERVED_1_BIT_QCOM = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkDeviceQueueCreateFlagBits]): VkDeviceQueueCreateFlags = - for flag in flags: - result = VkDeviceQueueCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkDeviceQueueCreateFlags): seq[VkDeviceQueueCreateFlagBits] = - for value in VkDeviceQueueCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDeviceQueueCreateFlags): bool = cint(a) == cint(b) -type - VkMemoryPropertyFlagBits* {.size: sizeof(cint).} = enum - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0b00000000000000000000000000000001 - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0b00000000000000000000000000000010 - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0b00000000000000000000000000000100 - VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0b00000000000000000000000000001000 - VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0b00000000000000000000000000010000 - VK_MEMORY_PROPERTY_PROTECTED_BIT = 0b00000000000000000000000000100000 - VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD = 0b00000000000000000000000001000000 - VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD = 0b00000000000000000000000010000000 - VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV = 0b00000000000000000000000100000000 -func toBits*(flags: openArray[VkMemoryPropertyFlagBits]): VkMemoryPropertyFlags = - for flag in flags: - result = VkMemoryPropertyFlags(uint(result) or uint(flag)) -func toEnums*(number: VkMemoryPropertyFlags): seq[VkMemoryPropertyFlagBits] = - for value in VkMemoryPropertyFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkMemoryPropertyFlags): bool = cint(a) == cint(b) -type - VkMemoryHeapFlagBits* {.size: sizeof(cint).} = enum - VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0b00000000000000000000000000000001 - VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0b00000000000000000000000000000010 - VK_MEMORY_HEAP_SEU_SAFE_BIT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkMemoryHeapFlagBits]): VkMemoryHeapFlags = - for flag in flags: - result = VkMemoryHeapFlags(uint(result) or uint(flag)) -func toEnums*(number: VkMemoryHeapFlags): seq[VkMemoryHeapFlagBits] = - for value in VkMemoryHeapFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkMemoryHeapFlags): bool = cint(a) == cint(b) -type - VkAccessFlagBits* {.size: sizeof(cint).} = enum - VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0b00000000000000000000000000000001 - VK_ACCESS_INDEX_READ_BIT = 0b00000000000000000000000000000010 - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0b00000000000000000000000000000100 - VK_ACCESS_UNIFORM_READ_BIT = 0b00000000000000000000000000001000 - VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0b00000000000000000000000000010000 - VK_ACCESS_SHADER_READ_BIT = 0b00000000000000000000000000100000 - VK_ACCESS_SHADER_WRITE_BIT = 0b00000000000000000000000001000000 - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0b00000000000000000000000010000000 - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0b00000000000000000000000100000000 - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0b00000000000000000000001000000000 - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0b00000000000000000000010000000000 - VK_ACCESS_TRANSFER_READ_BIT = 0b00000000000000000000100000000000 - VK_ACCESS_TRANSFER_WRITE_BIT = 0b00000000000000000001000000000000 - VK_ACCESS_HOST_READ_BIT = 0b00000000000000000010000000000000 - VK_ACCESS_HOST_WRITE_BIT = 0b00000000000000000100000000000000 - VK_ACCESS_MEMORY_READ_BIT = 0b00000000000000001000000000000000 - VK_ACCESS_MEMORY_WRITE_BIT = 0b00000000000000010000000000000000 - VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0b00000000000000100000000000000000 - VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0b00000000000001000000000000000000 - VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0b00000000000010000000000000000000 - VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0b00000000000100000000000000000000 - VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0b00000000001000000000000000000000 - VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0b00000000010000000000000000000000 - VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0b00000000100000000000000000000000 - VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0b00000001000000000000000000000000 - VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0b00000010000000000000000000000000 - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0b00000100000000000000000000000000 - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0b00001000000000000000000000000000 -func toBits*(flags: openArray[VkAccessFlagBits]): VkAccessFlags = - for flag in flags: - result = VkAccessFlags(uint(result) or uint(flag)) -func toEnums*(number: VkAccessFlags): seq[VkAccessFlagBits] = - for value in VkAccessFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkAccessFlags): bool = cint(a) == cint(b) -type - VkBufferUsageFlagBits* {.size: sizeof(cint).} = enum - VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 0b00000000000000000000000000000001 - VK_BUFFER_USAGE_TRANSFER_DST_BIT = 0b00000000000000000000000000000010 - VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0b00000000000000000000000000000100 - VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0b00000000000000000000000000001000 - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0b00000000000000000000000000010000 - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0b00000000000000000000000000100000 - VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0b00000000000000000000000001000000 - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0b00000000000000000000000010000000 - VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0b00000000000000000000000100000000 - VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0b00000000000000000000001000000000 - VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR = 0b00000000000000000000010000000000 - VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0b00000000000000000000100000000000 - VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0b00000000000000000001000000000000 - VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0b00000000000000000010000000000000 - VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0b00000000000000000100000000000000 - VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0b00000000000000001000000000000000 - VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0b00000000000000010000000000000000 - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT = 0b00000000000000100000000000000000 - VK_BUFFER_USAGE_RESERVED_18_BIT_QCOM = 0b00000000000001000000000000000000 - VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0b00000000000010000000000000000000 - VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0b00000000000100000000000000000000 - VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT = 0b00000000001000000000000000000000 - VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT = 0b00000000010000000000000000000000 - VK_BUFFER_USAGE_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT = 0b00000000100000000000000000000000 - VK_BUFFER_USAGE_MICROMAP_STORAGE_BIT_EXT = 0b00000001000000000000000000000000 - VK_BUFFER_USAGE_RESERVED_25_BIT_AMD = 0b00000010000000000000000000000000 - VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT = 0b00000100000000000000000000000000 -func toBits*(flags: openArray[VkBufferUsageFlagBits]): VkBufferUsageFlags = - for flag in flags: - result = VkBufferUsageFlags(uint(result) or uint(flag)) -func toEnums*(number: VkBufferUsageFlags): seq[VkBufferUsageFlagBits] = - for value in VkBufferUsageFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkBufferUsageFlags): bool = cint(a) == cint(b) -type - VkBufferCreateFlagBits* {.size: sizeof(cint).} = enum - VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0b00000000000000000000000000000001 - VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0b00000000000000000000000000000010 - VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0b00000000000000000000000000000100 - VK_BUFFER_CREATE_PROTECTED_BIT = 0b00000000000000000000000000001000 - VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0b00000000000000000000000000010000 - VK_BUFFER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000000000000000100000 -func toBits*(flags: openArray[VkBufferCreateFlagBits]): VkBufferCreateFlags = - for flag in flags: - result = VkBufferCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkBufferCreateFlags): seq[VkBufferCreateFlagBits] = - for value in VkBufferCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkBufferCreateFlags): bool = cint(a) == cint(b) -type - VkShaderStageFlagBits* {.size: sizeof(cint).} = enum - VK_SHADER_STAGE_VERTEX_BIT = 0b00000000000000000000000000000001 - VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0b00000000000000000000000000000010 - VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0b00000000000000000000000000000100 - VK_SHADER_STAGE_GEOMETRY_BIT = 0b00000000000000000000000000001000 - VK_SHADER_STAGE_FRAGMENT_BIT = 0b00000000000000000000000000010000 - VK_SHADER_STAGE_COMPUTE_BIT = 0b00000000000000000000000000100000 - VK_SHADER_STAGE_TASK_BIT_EXT = 0b00000000000000000000000001000000 - VK_SHADER_STAGE_MESH_BIT_EXT = 0b00000000000000000000000010000000 - VK_SHADER_STAGE_RAYGEN_BIT_KHR = 0b00000000000000000000000100000000 - VK_SHADER_STAGE_ANY_HIT_BIT_KHR = 0b00000000000000000000001000000000 - VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0b00000000000000000000010000000000 - VK_SHADER_STAGE_MISS_BIT_KHR = 0b00000000000000000000100000000000 - VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0b00000000000000000001000000000000 - VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0b00000000000000000010000000000000 - VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI = 0b00000000000000000100000000000000 - VK_SHADER_STAGE_EXT_483_RESERVE_15 = 0b00000000000000001000000000000000 - VK_SHADER_STAGE_EXT_483_RESERVE_16 = 0b00000000000000010000000000000000 - VK_SHADER_STAGE_EXT_483_RESERVE_17 = 0b00000000000000100000000000000000 - VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI = 0b00000000000010000000000000000000 -func toBits*(flags: openArray[VkShaderStageFlagBits]): VkShaderStageFlags = - for flag in flags: - result = VkShaderStageFlags(uint(result) or uint(flag)) -func toEnums*(number: VkShaderStageFlags): seq[VkShaderStageFlagBits] = - for value in VkShaderStageFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkShaderStageFlags): bool = cint(a) == cint(b) -const - VK_SHADER_STAGE_ALL_GRAPHICS* = 0x0000001F - VK_SHADER_STAGE_ALL* = 0x7FFFFFFF -type - VkImageUsageFlagBits* {.size: sizeof(cint).} = enum - VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0b00000000000000000000000000000001 - VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0b00000000000000000000000000000010 - VK_IMAGE_USAGE_SAMPLED_BIT = 0b00000000000000000000000000000100 - VK_IMAGE_USAGE_STORAGE_BIT = 0b00000000000000000000000000001000 - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0b00000000000000000000000000010000 - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0b00000000000000000000000000100000 - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0b00000000000000000000000001000000 - VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0b00000000000000000000000010000000 - VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b00000000000000000000000100000000 - VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0b00000000000000000000001000000000 - VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0b00000000000000000000010000000000 - VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0b00000000000000000000100000000000 - VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR = 0b00000000000000000001000000000000 - VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0b00000000000000000010000000000000 - VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0b00000000000000000100000000000000 - VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR = 0b00000000000000001000000000000000 - VK_IMAGE_USAGE_RESERVED_16_BIT_QCOM = 0b00000000000000010000000000000000 - VK_IMAGE_USAGE_RESERVED_17_BIT_QCOM = 0b00000000000000100000000000000000 - VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI = 0b00000000000001000000000000000000 - VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0b00000000000010000000000000000000 - VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM = 0b00000000000100000000000000000000 - VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM = 0b00000000001000000000000000000000 - VK_IMAGE_USAGE_RESERVED_22_BIT_EXT = 0b00000000010000000000000000000000 -func toBits*(flags: openArray[VkImageUsageFlagBits]): VkImageUsageFlags = - for flag in flags: - result = VkImageUsageFlags(uint(result) or uint(flag)) -func toEnums*(number: VkImageUsageFlags): seq[VkImageUsageFlagBits] = - for value in VkImageUsageFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkImageUsageFlags): bool = cint(a) == cint(b) -type - VkImageCreateFlagBits* {.size: sizeof(cint).} = enum - VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0b00000000000000000000000000000001 - VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0b00000000000000000000000000000010 - VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0b00000000000000000000000000000100 - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0b00000000000000000000000000001000 - VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0b00000000000000000000000000010000 - VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT = 0b00000000000000000000000000100000 - VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT = 0b00000000000000000000000001000000 - VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 0b00000000000000000000000010000000 - VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0b00000000000000000000000100000000 - VK_IMAGE_CREATE_DISJOINT_BIT = 0b00000000000000000000001000000000 - VK_IMAGE_CREATE_ALIAS_BIT = 0b00000000000000000000010000000000 - VK_IMAGE_CREATE_PROTECTED_BIT = 0b00000000000000000000100000000000 - VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0b00000000000000000001000000000000 - VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0b00000000000000000010000000000000 - VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT = 0b00000000000000000100000000000000 - VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM = 0b00000000000000001000000000000000 - VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000010000000000000000 - VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT = 0b00000000000000100000000000000000 - VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT = 0b00000000000001000000000000000000 - VK_IMAGE_CREATE_RESERVED_19_BIT_EXT = 0b00000000000010000000000000000000 -func toBits*(flags: openArray[VkImageCreateFlagBits]): VkImageCreateFlags = - for flag in flags: - result = VkImageCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkImageCreateFlags): seq[VkImageCreateFlagBits] = - for value in VkImageCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkImageCreateFlags): bool = cint(a) == cint(b) -type - VkImageViewCreateFlagBits* {.size: sizeof(cint).} = enum - VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0b00000000000000000000000000000001 - VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT = 0b00000000000000000000000000000010 - VK_IMAGE_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkImageViewCreateFlagBits]): VkImageViewCreateFlags = - for flag in flags: - result = VkImageViewCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkImageViewCreateFlags): seq[VkImageViewCreateFlagBits] = - for value in VkImageViewCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkImageViewCreateFlags): bool = cint(a) == cint(b) -type - VkSamplerCreateFlagBits* {.size: sizeof(cint).} = enum - VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0b00000000000000000000000000000001 - VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0b00000000000000000000000000000010 - VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT = 0b00000000000000000000000000000100 - VK_SAMPLER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000000000000000001000 - VK_SAMPLER_CREATE_IMAGE_PROCESSING_BIT_QCOM = 0b00000000000000000000000000010000 -func toBits*(flags: openArray[VkSamplerCreateFlagBits]): VkSamplerCreateFlags = - for flag in flags: - result = VkSamplerCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkSamplerCreateFlags): seq[VkSamplerCreateFlagBits] = - for value in VkSamplerCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSamplerCreateFlags): bool = cint(a) == cint(b) -type - VkPipelineCreateFlagBits* {.size: sizeof(cint).} = enum - VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0b00000000000000000000000000000001 - VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0b00000000000000000000000000000010 - VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0b00000000000000000000000000000100 - VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0b00000000000000000000000000001000 - VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0b00000000000000000000000000010000 - VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0b00000000000000000000000000100000 - VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR = 0b00000000000000000000000001000000 - VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0b00000000000000000000000010000000 - VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT = 0b00000000000000000000000100000000 - VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT = 0b00000000000000000000001000000000 - VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT = 0b00000000000000000000010000000000 - VK_PIPELINE_CREATE_LIBRARY_BIT_KHR = 0b00000000000000000000100000000000 - VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0b00000000000000000001000000000000 - VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0b00000000000000000010000000000000 - VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0b00000000000000000100000000000000 - VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0b00000000000000001000000000000000 - VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0b00000000000000010000000000000000 - VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0b00000000000000100000000000000000 - VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV = 0b00000000000001000000000000000000 - VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 0b00000000000010000000000000000000 - VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0b00000000000100000000000000000000 - VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b00000000001000000000000000000000 - VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0b00000000010000000000000000000000 - VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT = 0b00000000100000000000000000000000 - VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0b00000001000000000000000000000000 - VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0b00000010000000000000000000000000 - VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0b00000100000000000000000000000000 - VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT = 0b00001000000000000000000000000000 - VK_PIPELINE_CREATE_RESERVED_BIT_28_NV = 0b00010000000000000000000000000000 - VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT = 0b00100000000000000000000000000000 - VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT = 0b01000000000000000000000000000000 -func toBits*(flags: openArray[VkPipelineCreateFlagBits]): VkPipelineCreateFlags = - for flag in flags: - result = VkPipelineCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkPipelineCreateFlags): seq[VkPipelineCreateFlagBits] = - for value in VkPipelineCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPipelineCreateFlags): bool = cint(a) == cint(b) -type - VkPipelineShaderStageCreateFlagBits* {.size: sizeof(cint).} = enum - VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT = 0b00000000000000000000000000000001 - VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT = 0b00000000000000000000000000000010 - VK_PIPELINE_SHADER_STAGE_CREATE_RESERVED_3_BIT_KHR = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkPipelineShaderStageCreateFlagBits]): VkPipelineShaderStageCreateFlags = - for flag in flags: - result = VkPipelineShaderStageCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkPipelineShaderStageCreateFlags): seq[VkPipelineShaderStageCreateFlagBits] = - for value in VkPipelineShaderStageCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPipelineShaderStageCreateFlags): bool = cint(a) == cint(b) -type - VkColorComponentFlagBits* {.size: sizeof(cint).} = enum - VK_COLOR_COMPONENT_R_BIT = 0b00000000000000000000000000000001 - VK_COLOR_COMPONENT_G_BIT = 0b00000000000000000000000000000010 - VK_COLOR_COMPONENT_B_BIT = 0b00000000000000000000000000000100 - VK_COLOR_COMPONENT_A_BIT = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkColorComponentFlagBits]): VkColorComponentFlags = - for flag in flags: - result = VkColorComponentFlags(uint(result) or uint(flag)) -func toEnums*(number: VkColorComponentFlags): seq[VkColorComponentFlagBits] = - for value in VkColorComponentFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkColorComponentFlags): bool = cint(a) == cint(b) -type - VkFenceCreateFlagBits* {.size: sizeof(cint).} = enum - VK_FENCE_CREATE_SIGNALED_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkFenceCreateFlagBits]): VkFenceCreateFlags = - for flag in flags: - result = VkFenceCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkFenceCreateFlags): seq[VkFenceCreateFlagBits] = - for value in VkFenceCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkFenceCreateFlags): bool = cint(a) == cint(b) -type - VkFormatFeatureFlagBits* {.size: sizeof(cint).} = enum - VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0b00000000000000000000000000000001 - VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0b00000000000000000000000000000010 - VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0b00000000000000000000000000000100 - VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0b00000000000000000000000000001000 - VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0b00000000000000000000000000010000 - VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0b00000000000000000000000000100000 - VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0b00000000000000000000000001000000 - VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0b00000000000000000000000010000000 - VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0b00000000000000000000000100000000 - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0b00000000000000000000001000000000 - VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0b00000000000000000000010000000000 - VK_FORMAT_FEATURE_BLIT_DST_BIT = 0b00000000000000000000100000000000 - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0b00000000000000000001000000000000 - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 0b00000000000000000010000000000000 - VK_FORMAT_FEATURE_TRANSFER_SRC_BIT = 0b00000000000000000100000000000000 - VK_FORMAT_FEATURE_TRANSFER_DST_BIT = 0b00000000000000001000000000000000 - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0b00000000000000010000000000000000 - VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT = 0b00000000000000100000000000000000 - VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0b00000000000001000000000000000000 - VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0b00000000000010000000000000000000 - VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0b00000000000100000000000000000000 - VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0b00000000001000000000000000000000 - VK_FORMAT_FEATURE_DISJOINT_BIT = 0b00000000010000000000000000000000 - VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0b00000000100000000000000000000000 - VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0b00000001000000000000000000000000 - VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR = 0b00000010000000000000000000000000 - VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR = 0b00000100000000000000000000000000 - VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR = 0b00001000000000000000000000000000 - VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR = 0b00010000000000000000000000000000 - VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0b00100000000000000000000000000000 - VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b01000000000000000000000000000000 -func toBits*(flags: openArray[VkFormatFeatureFlagBits]): VkFormatFeatureFlags = - for flag in flags: - result = VkFormatFeatureFlags(uint(result) or uint(flag)) -func toEnums*(number: VkFormatFeatureFlags): seq[VkFormatFeatureFlagBits] = - for value in VkFormatFeatureFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkFormatFeatureFlags): bool = cint(a) == cint(b) -type - VkQueryControlFlagBits* {.size: sizeof(cint).} = enum - VK_QUERY_CONTROL_PRECISE_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkQueryControlFlagBits]): VkQueryControlFlags = - for flag in flags: - result = VkQueryControlFlags(uint(result) or uint(flag)) -func toEnums*(number: VkQueryControlFlags): seq[VkQueryControlFlagBits] = - for value in VkQueryControlFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkQueryControlFlags): bool = cint(a) == cint(b) -type - VkQueryResultFlagBits* {.size: sizeof(cint).} = enum - VK_QUERY_RESULT_64_BIT = 0b00000000000000000000000000000001 - VK_QUERY_RESULT_WAIT_BIT = 0b00000000000000000000000000000010 - VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0b00000000000000000000000000000100 - VK_QUERY_RESULT_PARTIAL_BIT = 0b00000000000000000000000000001000 - VK_QUERY_RESULT_WITH_STATUS_BIT_KHR = 0b00000000000000000000000000010000 -func toBits*(flags: openArray[VkQueryResultFlagBits]): VkQueryResultFlags = - for flag in flags: - result = VkQueryResultFlags(uint(result) or uint(flag)) -func toEnums*(number: VkQueryResultFlags): seq[VkQueryResultFlagBits] = - for value in VkQueryResultFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkQueryResultFlags): bool = cint(a) == cint(b) -type - VkCommandBufferUsageFlagBits* {.size: sizeof(cint).} = enum - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0b00000000000000000000000000000001 - VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0b00000000000000000000000000000010 - VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkCommandBufferUsageFlagBits]): VkCommandBufferUsageFlags = - for flag in flags: - result = VkCommandBufferUsageFlags(uint(result) or uint(flag)) -func toEnums*(number: VkCommandBufferUsageFlags): seq[VkCommandBufferUsageFlagBits] = - for value in VkCommandBufferUsageFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkCommandBufferUsageFlags): bool = cint(a) == cint(b) -type - VkQueryPipelineStatisticFlagBits* {.size: sizeof(cint).} = enum - VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0b00000000000000000000000000000001 - VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0b00000000000000000000000000000010 - VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0b00000000000000000000000000000100 - VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0b00000000000000000000000000001000 - VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0b00000000000000000000000000010000 - VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0b00000000000000000000000000100000 - VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0b00000000000000000000000001000000 - VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0b00000000000000000000000010000000 - VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0b00000000000000000000000100000000 - VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0b00000000000000000000001000000000 - VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0b00000000000000000000010000000000 - VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT = 0b00000000000000000000100000000000 - VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT = 0b00000000000000000001000000000000 - VK_QUERY_PIPELINE_STATISTIC_CLUSTER_CULLING_SHADER_INVOCATIONS_BIT_HUAWEI = 0b00000000000000000010000000000000 -func toBits*(flags: openArray[VkQueryPipelineStatisticFlagBits]): VkQueryPipelineStatisticFlags = - for flag in flags: - result = VkQueryPipelineStatisticFlags(uint(result) or uint(flag)) -func toEnums*(number: VkQueryPipelineStatisticFlags): seq[VkQueryPipelineStatisticFlagBits] = - for value in VkQueryPipelineStatisticFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkQueryPipelineStatisticFlags): bool = cint(a) == cint(b) -type - VkImageAspectFlagBits* {.size: sizeof(cint).} = enum - VK_IMAGE_ASPECT_COLOR_BIT = 0b00000000000000000000000000000001 - VK_IMAGE_ASPECT_DEPTH_BIT = 0b00000000000000000000000000000010 - VK_IMAGE_ASPECT_STENCIL_BIT = 0b00000000000000000000000000000100 - VK_IMAGE_ASPECT_METADATA_BIT = 0b00000000000000000000000000001000 - VK_IMAGE_ASPECT_PLANE_0_BIT = 0b00000000000000000000000000010000 - VK_IMAGE_ASPECT_PLANE_1_BIT = 0b00000000000000000000000000100000 - VK_IMAGE_ASPECT_PLANE_2_BIT = 0b00000000000000000000000001000000 - VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0b00000000000000000000000010000000 - VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0b00000000000000000000000100000000 - VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0b00000000000000000000001000000000 - VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0b00000000000000000000010000000000 -func toBits*(flags: openArray[VkImageAspectFlagBits]): VkImageAspectFlags = - for flag in flags: - result = VkImageAspectFlags(uint(result) or uint(flag)) -func toEnums*(number: VkImageAspectFlags): seq[VkImageAspectFlagBits] = - for value in VkImageAspectFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkImageAspectFlags): bool = cint(a) == cint(b) -type - VkSparseImageFormatFlagBits* {.size: sizeof(cint).} = enum - VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0b00000000000000000000000000000001 - VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0b00000000000000000000000000000010 - VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkSparseImageFormatFlagBits]): VkSparseImageFormatFlags = - for flag in flags: - result = VkSparseImageFormatFlags(uint(result) or uint(flag)) -func toEnums*(number: VkSparseImageFormatFlags): seq[VkSparseImageFormatFlagBits] = - for value in VkSparseImageFormatFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSparseImageFormatFlags): bool = cint(a) == cint(b) -type - VkSparseMemoryBindFlagBits* {.size: sizeof(cint).} = enum - VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkSparseMemoryBindFlagBits]): VkSparseMemoryBindFlags = - for flag in flags: - result = VkSparseMemoryBindFlags(uint(result) or uint(flag)) -func toEnums*(number: VkSparseMemoryBindFlags): seq[VkSparseMemoryBindFlagBits] = - for value in VkSparseMemoryBindFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSparseMemoryBindFlags): bool = cint(a) == cint(b) -type - VkPipelineStageFlagBits* {.size: sizeof(cint).} = enum - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0b00000000000000000000000000000001 - VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0b00000000000000000000000000000010 - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0b00000000000000000000000000000100 - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0b00000000000000000000000000001000 - VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0b00000000000000000000000000010000 - VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0b00000000000000000000000000100000 - VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0b00000000000000000000000001000000 - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0b00000000000000000000000010000000 - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0b00000000000000000000000100000000 - VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0b00000000000000000000001000000000 - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0b00000000000000000000010000000000 - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0b00000000000000000000100000000000 - VK_PIPELINE_STAGE_TRANSFER_BIT = 0b00000000000000000001000000000000 - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0b00000000000000000010000000000000 - VK_PIPELINE_STAGE_HOST_BIT = 0b00000000000000000100000000000000 - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0b00000000000000001000000000000000 - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0b00000000000000010000000000000000 - VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0b00000000000000100000000000000000 - VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0b00000000000001000000000000000000 - VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT = 0b00000000000010000000000000000000 - VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT = 0b00000000000100000000000000000000 - VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0b00000000001000000000000000000000 - VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b00000000010000000000000000000000 - VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0b00000000100000000000000000000000 - VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0b00000001000000000000000000000000 - VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0b00000010000000000000000000000000 -func toBits*(flags: openArray[VkPipelineStageFlagBits]): VkPipelineStageFlags = - for flag in flags: - result = VkPipelineStageFlags(uint(result) or uint(flag)) -func toEnums*(number: VkPipelineStageFlags): seq[VkPipelineStageFlagBits] = - for value in VkPipelineStageFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPipelineStageFlags): bool = cint(a) == cint(b) -type - VkCommandPoolCreateFlagBits* {.size: sizeof(cint).} = enum - VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0b00000000000000000000000000000001 - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0b00000000000000000000000000000010 - VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkCommandPoolCreateFlagBits]): VkCommandPoolCreateFlags = - for flag in flags: - result = VkCommandPoolCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkCommandPoolCreateFlags): seq[VkCommandPoolCreateFlagBits] = - for value in VkCommandPoolCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkCommandPoolCreateFlags): bool = cint(a) == cint(b) -type - VkCommandPoolResetFlagBits* {.size: sizeof(cint).} = enum - VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0b00000000000000000000000000000001 - VK_COMMAND_POOL_RESET_RESERVED_1_BIT_COREAVI = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkCommandPoolResetFlagBits]): VkCommandPoolResetFlags = - for flag in flags: - result = VkCommandPoolResetFlags(uint(result) or uint(flag)) -func toEnums*(number: VkCommandPoolResetFlags): seq[VkCommandPoolResetFlagBits] = - for value in VkCommandPoolResetFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkCommandPoolResetFlags): bool = cint(a) == cint(b) -type - VkCommandBufferResetFlagBits* {.size: sizeof(cint).} = enum - VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkCommandBufferResetFlagBits]): VkCommandBufferResetFlags = - for flag in flags: - result = VkCommandBufferResetFlags(uint(result) or uint(flag)) -func toEnums*(number: VkCommandBufferResetFlags): seq[VkCommandBufferResetFlagBits] = - for value in VkCommandBufferResetFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkCommandBufferResetFlags): bool = cint(a) == cint(b) -type - VkSampleCountFlagBits* {.size: sizeof(cint).} = enum - VK_SAMPLE_COUNT_1_BIT = 0b00000000000000000000000000000001 - VK_SAMPLE_COUNT_2_BIT = 0b00000000000000000000000000000010 - VK_SAMPLE_COUNT_4_BIT = 0b00000000000000000000000000000100 - VK_SAMPLE_COUNT_8_BIT = 0b00000000000000000000000000001000 - VK_SAMPLE_COUNT_16_BIT = 0b00000000000000000000000000010000 - VK_SAMPLE_COUNT_32_BIT = 0b00000000000000000000000000100000 - VK_SAMPLE_COUNT_64_BIT = 0b00000000000000000000000001000000 -func toBits*(flags: openArray[VkSampleCountFlagBits]): VkSampleCountFlags = - for flag in flags: - result = VkSampleCountFlags(uint(result) or uint(flag)) -func toEnums*(number: VkSampleCountFlags): seq[VkSampleCountFlagBits] = - for value in VkSampleCountFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSampleCountFlags): bool = cint(a) == cint(b) -type - VkAttachmentDescriptionFlagBits* {.size: sizeof(cint).} = enum - VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkAttachmentDescriptionFlagBits]): VkAttachmentDescriptionFlags = - for flag in flags: - result = VkAttachmentDescriptionFlags(uint(result) or uint(flag)) -func toEnums*(number: VkAttachmentDescriptionFlags): seq[VkAttachmentDescriptionFlagBits] = - for value in VkAttachmentDescriptionFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkAttachmentDescriptionFlags): bool = cint(a) == cint(b) -type - VkStencilFaceFlagBits* {.size: sizeof(cint).} = enum - VK_STENCIL_FACE_FRONT_BIT = 0b00000000000000000000000000000001 - VK_STENCIL_FACE_BACK_BIT = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkStencilFaceFlagBits]): VkStencilFaceFlags = - for flag in flags: - result = VkStencilFaceFlags(uint(result) or uint(flag)) -func toEnums*(number: VkStencilFaceFlags): seq[VkStencilFaceFlagBits] = - for value in VkStencilFaceFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkStencilFaceFlags): bool = cint(a) == cint(b) -const - VK_STENCIL_FACE_FRONT_AND_BACK* = 0x00000003 -type - VkDescriptorPoolCreateFlagBits* {.size: sizeof(cint).} = enum - VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0b00000000000000000000000000000001 - VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0b00000000000000000000000000000010 - VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkDescriptorPoolCreateFlagBits]): VkDescriptorPoolCreateFlags = - for flag in flags: - result = VkDescriptorPoolCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkDescriptorPoolCreateFlags): seq[VkDescriptorPoolCreateFlagBits] = - for value in VkDescriptorPoolCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDescriptorPoolCreateFlags): bool = cint(a) == cint(b) -type - VkDependencyFlagBits* {.size: sizeof(cint).} = enum - VK_DEPENDENCY_BY_REGION_BIT = 0b00000000000000000000000000000001 - VK_DEPENDENCY_VIEW_LOCAL_BIT = 0b00000000000000000000000000000010 - VK_DEPENDENCY_DEVICE_GROUP_BIT = 0b00000000000000000000000000000100 - VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkDependencyFlagBits]): VkDependencyFlags = - for flag in flags: - result = VkDependencyFlags(uint(result) or uint(flag)) -func toEnums*(number: VkDependencyFlags): seq[VkDependencyFlagBits] = - for value in VkDependencyFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDependencyFlags): bool = cint(a) == cint(b) -type - VkSemaphoreType* {.size: sizeof(cint).} = enum - VK_SEMAPHORE_TYPE_BINARY = 0 - VK_SEMAPHORE_TYPE_TIMELINE = 1 - VkSemaphoreWaitFlagBits* {.size: sizeof(cint).} = enum - VK_SEMAPHORE_WAIT_ANY_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkSemaphoreWaitFlagBits]): VkSemaphoreWaitFlags = - for flag in flags: - result = VkSemaphoreWaitFlags(uint(result) or uint(flag)) -func toEnums*(number: VkSemaphoreWaitFlags): seq[VkSemaphoreWaitFlagBits] = - for value in VkSemaphoreWaitFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSemaphoreWaitFlags): bool = cint(a) == cint(b) -type - VkPresentModeKHR* {.size: sizeof(cint).} = enum - VK_PRESENT_MODE_IMMEDIATE_KHR = 0 - VK_PRESENT_MODE_MAILBOX_KHR = 1 - VK_PRESENT_MODE_FIFO_KHR = 2 - VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3 - VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000 - VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001 - VkColorSpaceKHR* {.size: sizeof(cint).} = enum - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0 - VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001 - VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002 - VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104003 - VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004 - VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005 - VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006 - VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007 - VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008 - VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009 - VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010 - VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011 - VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012 - VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013 - VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014 - VK_COLOR_SPACE_DISPLAY_NATIVE_AMD = 1000213000 - VkDisplayPlaneAlphaFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0b00000000000000000000000000000001 - VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0b00000000000000000000000000000010 - VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0b00000000000000000000000000000100 - VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkDisplayPlaneAlphaFlagBitsKHR]): VkDisplayPlaneAlphaFlagsKHR = - for flag in flags: - result = VkDisplayPlaneAlphaFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkDisplayPlaneAlphaFlagsKHR): seq[VkDisplayPlaneAlphaFlagBitsKHR] = - for value in VkDisplayPlaneAlphaFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDisplayPlaneAlphaFlagsKHR): bool = cint(a) == cint(b) -type - VkCompositeAlphaFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0b00000000000000000000000000000001 - VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0b00000000000000000000000000000010 - VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0b00000000000000000000000000000100 - VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkCompositeAlphaFlagBitsKHR]): VkCompositeAlphaFlagsKHR = - for flag in flags: - result = VkCompositeAlphaFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkCompositeAlphaFlagsKHR): seq[VkCompositeAlphaFlagBitsKHR] = - for value in VkCompositeAlphaFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkCompositeAlphaFlagsKHR): bool = cint(a) == cint(b) -type - VkSurfaceTransformFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0b00000000000000000000000000000001 - VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0b00000000000000000000000000000010 - VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0b00000000000000000000000000000100 - VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0b00000000000000000000000000001000 - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0b00000000000000000000000000010000 - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0b00000000000000000000000000100000 - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0b00000000000000000000000001000000 - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0b00000000000000000000000010000000 - VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0b00000000000000000000000100000000 -func toBits*(flags: openArray[VkSurfaceTransformFlagBitsKHR]): VkSurfaceTransformFlagsKHR = - for flag in flags: - result = VkSurfaceTransformFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkSurfaceTransformFlagsKHR): seq[VkSurfaceTransformFlagBitsKHR] = - for value in VkSurfaceTransformFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSurfaceTransformFlagsKHR): bool = cint(a) == cint(b) -type - VkSwapchainImageUsageFlagBitsANDROID* {.size: sizeof(cint).} = enum - VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkSwapchainImageUsageFlagBitsANDROID]): VkSwapchainImageUsageFlagsANDROID = - for flag in flags: - result = VkSwapchainImageUsageFlagsANDROID(uint(result) or uint(flag)) -func toEnums*(number: VkSwapchainImageUsageFlagsANDROID): seq[VkSwapchainImageUsageFlagBitsANDROID] = - for value in VkSwapchainImageUsageFlagBitsANDROID.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSwapchainImageUsageFlagsANDROID): bool = cint(a) == cint(b) -type - VkTimeDomainEXT* {.size: sizeof(cint).} = enum - VK_TIME_DOMAIN_DEVICE_EXT = 0 - VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = 1 - VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = 2 - VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = 3 - VkDebugReportFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0b00000000000000000000000000000001 - VK_DEBUG_REPORT_WARNING_BIT_EXT = 0b00000000000000000000000000000010 - VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0b00000000000000000000000000000100 - VK_DEBUG_REPORT_ERROR_BIT_EXT = 0b00000000000000000000000000001000 - VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0b00000000000000000000000000010000 -func toBits*(flags: openArray[VkDebugReportFlagBitsEXT]): VkDebugReportFlagsEXT = - for flag in flags: - result = VkDebugReportFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkDebugReportFlagsEXT): seq[VkDebugReportFlagBitsEXT] = - for value in VkDebugReportFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDebugReportFlagsEXT): bool = cint(a) == cint(b) -type - VkDebugReportObjectTypeEXT* {.size: sizeof(cint).} = enum - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0 - VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1 - VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT = 2 - VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT = 3 - VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT = 4 - VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT = 5 - VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT = 6 - VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT = 7 - VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT = 8 - VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT = 9 - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT = 10 - VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT = 11 - VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT = 12 - VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT = 13 - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT = 14 - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT = 15 - VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT = 16 - VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT = 17 - VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT = 18 - VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT = 19 - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT = 20 - VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT = 21 - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT = 22 - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT = 23 - VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT = 24 - VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT = 25 - VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26 - VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27 - VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28 - VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29 - VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30 - VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33 - VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT = 1000029000 - VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT = 1000029001 - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000 - VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000150000 - VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000 - VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000 - VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT = 1000366000 - VkDeviceMemoryReportEventTypeEXT* {.size: sizeof(cint).} = enum - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT = 0 - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT = 1 - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT = 2 - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT = 3 - VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT = 4 - VkRasterizationOrderAMD* {.size: sizeof(cint).} = enum - VK_RASTERIZATION_ORDER_STRICT_AMD = 0 - VK_RASTERIZATION_ORDER_RELAXED_AMD = 1 - VkExternalMemoryHandleTypeFlagBitsNV* {.size: sizeof(cint).} = enum - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0b00000000000000000000000000000001 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0b00000000000000000000000000000010 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0b00000000000000000000000000000100 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkExternalMemoryHandleTypeFlagBitsNV]): VkExternalMemoryHandleTypeFlagsNV = - for flag in flags: - result = VkExternalMemoryHandleTypeFlagsNV(uint(result) or uint(flag)) -func toEnums*(number: VkExternalMemoryHandleTypeFlagsNV): seq[VkExternalMemoryHandleTypeFlagBitsNV] = - for value in VkExternalMemoryHandleTypeFlagBitsNV.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkExternalMemoryHandleTypeFlagsNV): bool = cint(a) == cint(b) -type - VkExternalMemoryFeatureFlagBitsNV* {.size: sizeof(cint).} = enum - VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0b00000000000000000000000000000001 - VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0b00000000000000000000000000000010 - VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkExternalMemoryFeatureFlagBitsNV]): VkExternalMemoryFeatureFlagsNV = - for flag in flags: - result = VkExternalMemoryFeatureFlagsNV(uint(result) or uint(flag)) -func toEnums*(number: VkExternalMemoryFeatureFlagsNV): seq[VkExternalMemoryFeatureFlagBitsNV] = - for value in VkExternalMemoryFeatureFlagBitsNV.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkExternalMemoryFeatureFlagsNV): bool = cint(a) == cint(b) -type - VkValidationCheckEXT* {.size: sizeof(cint).} = enum - VK_VALIDATION_CHECK_ALL_EXT = 0 - VK_VALIDATION_CHECK_SHADERS_EXT = 1 - VkValidationFeatureEnableEXT* {.size: sizeof(cint).} = enum - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0 - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1 - VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2 - VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3 - VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT = 4 - VkValidationFeatureDisableEXT* {.size: sizeof(cint).} = enum - VK_VALIDATION_FEATURE_DISABLE_ALL_EXT = 0 - VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT = 1 - VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT = 2 - VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT = 3 - VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4 - VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5 - VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6 - VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT = 7 - VkSubgroupFeatureFlagBits* {.size: sizeof(cint).} = enum - VK_SUBGROUP_FEATURE_BASIC_BIT = 0b00000000000000000000000000000001 - VK_SUBGROUP_FEATURE_VOTE_BIT = 0b00000000000000000000000000000010 - VK_SUBGROUP_FEATURE_ARITHMETIC_BIT = 0b00000000000000000000000000000100 - VK_SUBGROUP_FEATURE_BALLOT_BIT = 0b00000000000000000000000000001000 - VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 0b00000000000000000000000000010000 - VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0b00000000000000000000000000100000 - VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0b00000000000000000000000001000000 - VK_SUBGROUP_FEATURE_QUAD_BIT = 0b00000000000000000000000010000000 - VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV = 0b00000000000000000000000100000000 -func toBits*(flags: openArray[VkSubgroupFeatureFlagBits]): VkSubgroupFeatureFlags = - for flag in flags: - result = VkSubgroupFeatureFlags(uint(result) or uint(flag)) -func toEnums*(number: VkSubgroupFeatureFlags): seq[VkSubgroupFeatureFlagBits] = - for value in VkSubgroupFeatureFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSubgroupFeatureFlags): bool = cint(a) == cint(b) -type - VkIndirectCommandsLayoutUsageFlagBitsNV* {.size: sizeof(cint).} = enum - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0b00000000000000000000000000000001 - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0b00000000000000000000000000000010 - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkIndirectCommandsLayoutUsageFlagBitsNV]): VkIndirectCommandsLayoutUsageFlagsNV = - for flag in flags: - result = VkIndirectCommandsLayoutUsageFlagsNV(uint(result) or uint(flag)) -func toEnums*(number: VkIndirectCommandsLayoutUsageFlagsNV): seq[VkIndirectCommandsLayoutUsageFlagBitsNV] = - for value in VkIndirectCommandsLayoutUsageFlagBitsNV.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkIndirectCommandsLayoutUsageFlagsNV): bool = cint(a) == cint(b) -type - VkIndirectStateFlagBitsNV* {.size: sizeof(cint).} = enum - VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkIndirectStateFlagBitsNV]): VkIndirectStateFlagsNV = - for flag in flags: - result = VkIndirectStateFlagsNV(uint(result) or uint(flag)) -func toEnums*(number: VkIndirectStateFlagsNV): seq[VkIndirectStateFlagBitsNV] = - for value in VkIndirectStateFlagBitsNV.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkIndirectStateFlagsNV): bool = cint(a) == cint(b) -type - VkIndirectCommandsTokenTypeNV* {.size: sizeof(cint).} = enum - VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV = 0 - VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV = 1 - VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV = 2 - VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV = 3 - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV = 4 - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5 - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6 - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7 - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV = 1000328000 - VkPrivateDataSlotCreateFlagBits* {.size: sizeof(cint).} = enum - VK_PRIVATE_DATA_SLOT_CREATE_RESERVED_0_BIT_NV = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkPrivateDataSlotCreateFlagBits]): VkPrivateDataSlotCreateFlags = - for flag in flags: - result = VkPrivateDataSlotCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkPrivateDataSlotCreateFlags): seq[VkPrivateDataSlotCreateFlagBits] = - for value in VkPrivateDataSlotCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPrivateDataSlotCreateFlags): bool = cint(a) == cint(b) -type - VkDescriptorSetLayoutCreateFlagBits* {.size: sizeof(cint).} = enum - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0b00000000000000000000000000000001 - VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0b00000000000000000000000000000010 - VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT = 0b00000000000000000000000000000100 - VK_DESCRIPTOR_SET_LAYOUT_CREATE_RESERVED_3_BIT_AMD = 0b00000000000000000000000000001000 - VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT = 0b00000000000000000000000000010000 - VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT = 0b00000000000000000000000000100000 -func toBits*(flags: openArray[VkDescriptorSetLayoutCreateFlagBits]): VkDescriptorSetLayoutCreateFlags = - for flag in flags: - result = VkDescriptorSetLayoutCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkDescriptorSetLayoutCreateFlags): seq[VkDescriptorSetLayoutCreateFlagBits] = - for value in VkDescriptorSetLayoutCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDescriptorSetLayoutCreateFlags): bool = cint(a) == cint(b) -type - VkExternalMemoryHandleTypeFlagBits* {.size: sizeof(cint).} = enum - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 0b00000000000000000000000000000001 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0b00000000000000000000000000000010 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0b00000000000000000000000000000100 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 0b00000000000000000000000000001000 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 0b00000000000000000000000000010000 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 0b00000000000000000000000000100000 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 0b00000000000000000000000001000000 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT = 0b00000000000000000000000010000000 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0b00000000000000000000000100000000 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT = 0b00000000000000000000001000000000 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID = 0b00000000000000000000010000000000 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA = 0b00000000000000000000100000000000 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV = 0b00000000000000000001000000000000 - VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCI_BUF_BIT_NV = 0b00000000000000000010000000000000 -func toBits*(flags: openArray[VkExternalMemoryHandleTypeFlagBits]): VkExternalMemoryHandleTypeFlags = - for flag in flags: - result = VkExternalMemoryHandleTypeFlags(uint(result) or uint(flag)) -func toEnums*(number: VkExternalMemoryHandleTypeFlags): seq[VkExternalMemoryHandleTypeFlagBits] = - for value in VkExternalMemoryHandleTypeFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkExternalMemoryHandleTypeFlags): bool = cint(a) == cint(b) -type - VkExternalMemoryFeatureFlagBits* {.size: sizeof(cint).} = enum - VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 0b00000000000000000000000000000001 - VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 0b00000000000000000000000000000010 - VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkExternalMemoryFeatureFlagBits]): VkExternalMemoryFeatureFlags = - for flag in flags: - result = VkExternalMemoryFeatureFlags(uint(result) or uint(flag)) -func toEnums*(number: VkExternalMemoryFeatureFlags): seq[VkExternalMemoryFeatureFlagBits] = - for value in VkExternalMemoryFeatureFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkExternalMemoryFeatureFlags): bool = cint(a) == cint(b) -type - VkExternalSemaphoreHandleTypeFlagBits* {.size: sizeof(cint).} = enum - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 0b00000000000000000000000000000001 - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0b00000000000000000000000000000010 - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0b00000000000000000000000000000100 - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0b00000000000000000000000000001000 - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0b00000000000000000000000000010000 - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SCI_SYNC_OBJ_BIT_NV = 0b00000000000000000000000000100000 - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA = 0b00000000000000000000000010000000 -func toBits*(flags: openArray[VkExternalSemaphoreHandleTypeFlagBits]): VkExternalSemaphoreHandleTypeFlags = - for flag in flags: - result = VkExternalSemaphoreHandleTypeFlags(uint(result) or uint(flag)) -func toEnums*(number: VkExternalSemaphoreHandleTypeFlags): seq[VkExternalSemaphoreHandleTypeFlagBits] = - for value in VkExternalSemaphoreHandleTypeFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkExternalSemaphoreHandleTypeFlags): bool = cint(a) == cint(b) -type - VkExternalSemaphoreFeatureFlagBits* {.size: sizeof(cint).} = enum - VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 0b00000000000000000000000000000001 - VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkExternalSemaphoreFeatureFlagBits]): VkExternalSemaphoreFeatureFlags = - for flag in flags: - result = VkExternalSemaphoreFeatureFlags(uint(result) or uint(flag)) -func toEnums*(number: VkExternalSemaphoreFeatureFlags): seq[VkExternalSemaphoreFeatureFlagBits] = - for value in VkExternalSemaphoreFeatureFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkExternalSemaphoreFeatureFlags): bool = cint(a) == cint(b) -type - VkSemaphoreImportFlagBits* {.size: sizeof(cint).} = enum - VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkSemaphoreImportFlagBits]): VkSemaphoreImportFlags = - for flag in flags: - result = VkSemaphoreImportFlags(uint(result) or uint(flag)) -func toEnums*(number: VkSemaphoreImportFlags): seq[VkSemaphoreImportFlagBits] = - for value in VkSemaphoreImportFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSemaphoreImportFlags): bool = cint(a) == cint(b) -type - VkExternalFenceHandleTypeFlagBits* {.size: sizeof(cint).} = enum - VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 0b00000000000000000000000000000001 - VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0b00000000000000000000000000000010 - VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0b00000000000000000000000000000100 - VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 0b00000000000000000000000000001000 - VK_EXTERNAL_FENCE_HANDLE_TYPE_SCI_SYNC_OBJ_BIT_NV = 0b00000000000000000000000000010000 - VK_EXTERNAL_FENCE_HANDLE_TYPE_SCI_SYNC_FENCE_BIT_NV = 0b00000000000000000000000000100000 -func toBits*(flags: openArray[VkExternalFenceHandleTypeFlagBits]): VkExternalFenceHandleTypeFlags = - for flag in flags: - result = VkExternalFenceHandleTypeFlags(uint(result) or uint(flag)) -func toEnums*(number: VkExternalFenceHandleTypeFlags): seq[VkExternalFenceHandleTypeFlagBits] = - for value in VkExternalFenceHandleTypeFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkExternalFenceHandleTypeFlags): bool = cint(a) == cint(b) -type - VkExternalFenceFeatureFlagBits* {.size: sizeof(cint).} = enum - VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 0b00000000000000000000000000000001 - VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkExternalFenceFeatureFlagBits]): VkExternalFenceFeatureFlags = - for flag in flags: - result = VkExternalFenceFeatureFlags(uint(result) or uint(flag)) -func toEnums*(number: VkExternalFenceFeatureFlags): seq[VkExternalFenceFeatureFlagBits] = - for value in VkExternalFenceFeatureFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkExternalFenceFeatureFlags): bool = cint(a) == cint(b) -type - VkFenceImportFlagBits* {.size: sizeof(cint).} = enum - VK_FENCE_IMPORT_TEMPORARY_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkFenceImportFlagBits]): VkFenceImportFlags = - for flag in flags: - result = VkFenceImportFlags(uint(result) or uint(flag)) -func toEnums*(number: VkFenceImportFlags): seq[VkFenceImportFlagBits] = - for value in VkFenceImportFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkFenceImportFlags): bool = cint(a) == cint(b) -type - VkSurfaceCounterFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_SURFACE_COUNTER_VBLANK_BIT_EXT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkSurfaceCounterFlagBitsEXT]): VkSurfaceCounterFlagsEXT = - for flag in flags: - result = VkSurfaceCounterFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkSurfaceCounterFlagsEXT): seq[VkSurfaceCounterFlagBitsEXT] = - for value in VkSurfaceCounterFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSurfaceCounterFlagsEXT): bool = cint(a) == cint(b) -type - VkDisplayPowerStateEXT* {.size: sizeof(cint).} = enum - VK_DISPLAY_POWER_STATE_OFF_EXT = 0 - VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1 - VK_DISPLAY_POWER_STATE_ON_EXT = 2 - VkDeviceEventTypeEXT* {.size: sizeof(cint).} = enum - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0 - VkDisplayEventTypeEXT* {.size: sizeof(cint).} = enum - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0 - VkPeerMemoryFeatureFlagBits* {.size: sizeof(cint).} = enum - VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0b00000000000000000000000000000001 - VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0b00000000000000000000000000000010 - VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0b00000000000000000000000000000100 - VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkPeerMemoryFeatureFlagBits]): VkPeerMemoryFeatureFlags = - for flag in flags: - result = VkPeerMemoryFeatureFlags(uint(result) or uint(flag)) -func toEnums*(number: VkPeerMemoryFeatureFlags): seq[VkPeerMemoryFeatureFlagBits] = - for value in VkPeerMemoryFeatureFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPeerMemoryFeatureFlags): bool = cint(a) == cint(b) -type - VkMemoryAllocateFlagBits* {.size: sizeof(cint).} = enum - VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0b00000000000000000000000000000001 - VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 0b00000000000000000000000000000010 - VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkMemoryAllocateFlagBits]): VkMemoryAllocateFlags = - for flag in flags: - result = VkMemoryAllocateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkMemoryAllocateFlags): seq[VkMemoryAllocateFlagBits] = - for value in VkMemoryAllocateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkMemoryAllocateFlags): bool = cint(a) == cint(b) -type - VkDeviceGroupPresentModeFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0b00000000000000000000000000000001 - VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0b00000000000000000000000000000010 - VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0b00000000000000000000000000000100 - VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkDeviceGroupPresentModeFlagBitsKHR]): VkDeviceGroupPresentModeFlagsKHR = - for flag in flags: - result = VkDeviceGroupPresentModeFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkDeviceGroupPresentModeFlagsKHR): seq[VkDeviceGroupPresentModeFlagBitsKHR] = - for value in VkDeviceGroupPresentModeFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDeviceGroupPresentModeFlagsKHR): bool = cint(a) == cint(b) -type - VkSwapchainCreateFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0b00000000000000000000000000000001 - VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0b00000000000000000000000000000010 - VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0b00000000000000000000000000000100 - VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT = 0b00000000000000000000000000001000 - VK_SWAPCHAIN_CREATE_RESERVED_4_BIT_EXT = 0b00000000000000000000000000010000 -func toBits*(flags: openArray[VkSwapchainCreateFlagBitsKHR]): VkSwapchainCreateFlagsKHR = - for flag in flags: - result = VkSwapchainCreateFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkSwapchainCreateFlagsKHR): seq[VkSwapchainCreateFlagBitsKHR] = - for value in VkSwapchainCreateFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSwapchainCreateFlagsKHR): bool = cint(a) == cint(b) -type - VkViewportCoordinateSwizzleNV* {.size: sizeof(cint).} = enum - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0 - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1 - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2 - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3 - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4 - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5 - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6 - VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7 - VkDiscardRectangleModeEXT* {.size: sizeof(cint).} = enum - VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0 - VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1 - VkSubpassDescriptionFlagBits* {.size: sizeof(cint).} = enum - VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0b00000000000000000000000000000001 - VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0b00000000000000000000000000000010 - VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM = 0b00000000000000000000000000000100 - VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM = 0b00000000000000000000000000001000 - VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT = 0b00000000000000000000000000010000 - VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0b00000000000000000000000000100000 - VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0b00000000000000000000000001000000 - VK_SUBPASS_DESCRIPTION_ENABLE_LEGACY_DITHERING_BIT_EXT = 0b00000000000000000000000010000000 -func toBits*(flags: openArray[VkSubpassDescriptionFlagBits]): VkSubpassDescriptionFlags = - for flag in flags: - result = VkSubpassDescriptionFlags(uint(result) or uint(flag)) -func toEnums*(number: VkSubpassDescriptionFlags): seq[VkSubpassDescriptionFlagBits] = - for value in VkSubpassDescriptionFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSubpassDescriptionFlags): bool = cint(a) == cint(b) -type - VkPointClippingBehavior* {.size: sizeof(cint).} = enum - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0 - VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1 - VkSamplerReductionMode* {.size: sizeof(cint).} = enum - VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0 - VK_SAMPLER_REDUCTION_MODE_MIN = 1 - VK_SAMPLER_REDUCTION_MODE_MAX = 2 - VkTessellationDomainOrigin* {.size: sizeof(cint).} = enum - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0 - VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1 - VkSamplerYcbcrModelConversion* {.size: sizeof(cint).} = enum - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0 - VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1 - VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2 - VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3 - VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4 - VkSamplerYcbcrRange* {.size: sizeof(cint).} = enum - VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0 - VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1 - VkChromaLocation* {.size: sizeof(cint).} = enum - VK_CHROMA_LOCATION_COSITED_EVEN = 0 - VK_CHROMA_LOCATION_MIDPOINT = 1 - VkBlendOverlapEXT* {.size: sizeof(cint).} = enum - VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0 - VK_BLEND_OVERLAP_DISJOINT_EXT = 1 - VK_BLEND_OVERLAP_CONJOINT_EXT = 2 - VkCoverageModulationModeNV* {.size: sizeof(cint).} = enum - VK_COVERAGE_MODULATION_MODE_NONE_NV = 0 - VK_COVERAGE_MODULATION_MODE_RGB_NV = 1 - VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2 - VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3 - VkCoverageReductionModeNV* {.size: sizeof(cint).} = enum - VK_COVERAGE_REDUCTION_MODE_MERGE_NV = 0 - VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV = 1 - VkValidationCacheHeaderVersionEXT* {.size: sizeof(cint).} = enum - VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1 - VkShaderInfoTypeAMD* {.size: sizeof(cint).} = enum - VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0 - VK_SHADER_INFO_TYPE_BINARY_AMD = 1 - VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2 - VkQueueGlobalPriorityKHR* {.size: sizeof(cint).} = enum - VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR = 128 - VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR = 256 - VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR = 512 - VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR = 1024 - VkDebugUtilsMessageSeverityFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0b00000000000000000000000000000001 - VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0b00000000000000000000000000010000 - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0b00000000000000000000000100000000 - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0b00000000000000000001000000000000 -func toBits*(flags: openArray[VkDebugUtilsMessageSeverityFlagBitsEXT]): VkDebugUtilsMessageSeverityFlagsEXT = - for flag in flags: - result = VkDebugUtilsMessageSeverityFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkDebugUtilsMessageSeverityFlagsEXT): seq[VkDebugUtilsMessageSeverityFlagBitsEXT] = - for value in VkDebugUtilsMessageSeverityFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDebugUtilsMessageSeverityFlagsEXT): bool = cint(a) == cint(b) -type - VkDebugUtilsMessageTypeFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0b00000000000000000000000000000001 - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0b00000000000000000000000000000010 - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0b00000000000000000000000000000100 - VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkDebugUtilsMessageTypeFlagBitsEXT]): VkDebugUtilsMessageTypeFlagsEXT = - for flag in flags: - result = VkDebugUtilsMessageTypeFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkDebugUtilsMessageTypeFlagsEXT): seq[VkDebugUtilsMessageTypeFlagBitsEXT] = - for value in VkDebugUtilsMessageTypeFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDebugUtilsMessageTypeFlagsEXT): bool = cint(a) == cint(b) -type - VkConservativeRasterizationModeEXT* {.size: sizeof(cint).} = enum - VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0 - VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1 - VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2 - VkDescriptorBindingFlagBits* {.size: sizeof(cint).} = enum - VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 0b00000000000000000000000000000001 - VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0b00000000000000000000000000000010 - VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0b00000000000000000000000000000100 - VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0b00000000000000000000000000001000 - VK_DESCRIPTOR_BINDING_RESERVED_4_BIT_QCOM = 0b00000000000000000000000000010000 -func toBits*(flags: openArray[VkDescriptorBindingFlagBits]): VkDescriptorBindingFlags = - for flag in flags: - result = VkDescriptorBindingFlags(uint(result) or uint(flag)) -func toEnums*(number: VkDescriptorBindingFlags): seq[VkDescriptorBindingFlagBits] = - for value in VkDescriptorBindingFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDescriptorBindingFlags): bool = cint(a) == cint(b) -type - VkVendorId* {.size: sizeof(cint).} = enum - VK_VENDOR_ID_VIV = 65537 - VK_VENDOR_ID_VSI = 65538 - VK_VENDOR_ID_KAZAN = 65539 - VK_VENDOR_ID_CODEPLAY = 65540 - VK_VENDOR_ID_MESA = 65541 - VK_VENDOR_ID_POCL = 65542 - VkDriverId* {.size: sizeof(cint).} = enum - VK_DRIVER_ID_AMD_PROPRIETARY = 1 - VK_DRIVER_ID_AMD_OPEN_SOURCE = 2 - VK_DRIVER_ID_MESA_RADV = 3 - VK_DRIVER_ID_NVIDIA_PROPRIETARY = 4 - VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS = 5 - VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA = 6 - VK_DRIVER_ID_IMAGINATION_PROPRIETARY = 7 - VK_DRIVER_ID_QUALCOMM_PROPRIETARY = 8 - VK_DRIVER_ID_ARM_PROPRIETARY = 9 - VK_DRIVER_ID_GOOGLE_SWIFTSHADER = 10 - VK_DRIVER_ID_GGP_PROPRIETARY = 11 - VK_DRIVER_ID_BROADCOM_PROPRIETARY = 12 - VK_DRIVER_ID_MESA_LLVMPIPE = 13 - VK_DRIVER_ID_MOLTENVK = 14 - VK_DRIVER_ID_COREAVI_PROPRIETARY = 15 - VK_DRIVER_ID_JUICE_PROPRIETARY = 16 - VK_DRIVER_ID_VERISILICON_PROPRIETARY = 17 - VK_DRIVER_ID_MESA_TURNIP = 18 - VK_DRIVER_ID_MESA_V3DV = 19 - VK_DRIVER_ID_MESA_PANVK = 20 - VK_DRIVER_ID_SAMSUNG_PROPRIETARY = 21 - VK_DRIVER_ID_MESA_VENUS = 22 - VK_DRIVER_ID_MESA_DOZEN = 23 - VK_DRIVER_ID_MESA_NVK = 24 - VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA = 25 - VkConditionalRenderingFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkConditionalRenderingFlagBitsEXT]): VkConditionalRenderingFlagsEXT = - for flag in flags: - result = VkConditionalRenderingFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkConditionalRenderingFlagsEXT): seq[VkConditionalRenderingFlagBitsEXT] = - for value in VkConditionalRenderingFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkConditionalRenderingFlagsEXT): bool = cint(a) == cint(b) -type - VkResolveModeFlagBits* {.size: sizeof(cint).} = enum - VK_RESOLVE_MODE_SAMPLE_ZERO_BIT = 0b00000000000000000000000000000001 - VK_RESOLVE_MODE_AVERAGE_BIT = 0b00000000000000000000000000000010 - VK_RESOLVE_MODE_MIN_BIT = 0b00000000000000000000000000000100 - VK_RESOLVE_MODE_MAX_BIT = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkResolveModeFlagBits]): VkResolveModeFlags = - for flag in flags: - result = VkResolveModeFlags(uint(result) or uint(flag)) -func toEnums*(number: VkResolveModeFlags): seq[VkResolveModeFlagBits] = - for value in VkResolveModeFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkResolveModeFlags): bool = cint(a) == cint(b) -const - VK_RESOLVE_MODE_NONE* = 0 -type - VkShadingRatePaletteEntryNV* {.size: sizeof(cint).} = enum - VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0 - VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1 - VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2 - VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3 - VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4 - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5 - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6 - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7 - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8 - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9 - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10 - VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11 - VkCoarseSampleOrderTypeNV* {.size: sizeof(cint).} = enum - VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0 - VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1 - VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2 - VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3 - VkGeometryInstanceFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0b00000000000000000000000000000001 - VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR = 0b00000000000000000000000000000010 - VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0b00000000000000000000000000000100 - VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0b00000000000000000000000000001000 - VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT = 0b00000000000000000000000000010000 - VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT = 0b00000000000000000000000000100000 -func toBits*(flags: openArray[VkGeometryInstanceFlagBitsKHR]): VkGeometryInstanceFlagsKHR = - for flag in flags: - result = VkGeometryInstanceFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkGeometryInstanceFlagsKHR): seq[VkGeometryInstanceFlagBitsKHR] = - for value in VkGeometryInstanceFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkGeometryInstanceFlagsKHR): bool = cint(a) == cint(b) -type - VkGeometryFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_GEOMETRY_OPAQUE_BIT_KHR = 0b00000000000000000000000000000001 - VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkGeometryFlagBitsKHR]): VkGeometryFlagsKHR = - for flag in flags: - result = VkGeometryFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkGeometryFlagsKHR): seq[VkGeometryFlagBitsKHR] = - for value in VkGeometryFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkGeometryFlagsKHR): bool = cint(a) == cint(b) -type - VkBuildAccelerationStructureFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0b00000000000000000000000000000001 - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0b00000000000000000000000000000010 - VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0b00000000000000000000000000000100 - VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0b00000000000000000000000000001000 - VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0b00000000000000000000000000010000 - VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV = 0b00000000000000000000000000100000 - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT = 0b00000000000000000000000001000000 - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT = 0b00000000000000000000000010000000 - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT = 0b00000000000000000000000100000000 - VK_BUILD_ACCELERATION_STRUCTURE_RESERVED_BIT_9_NV = 0b00000000000000000000001000000000 - VK_BUILD_ACCELERATION_STRUCTURE_RESERVED_BIT_10_NV = 0b00000000000000000000010000000000 -func toBits*(flags: openArray[VkBuildAccelerationStructureFlagBitsKHR]): VkBuildAccelerationStructureFlagsKHR = - for flag in flags: - result = VkBuildAccelerationStructureFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkBuildAccelerationStructureFlagsKHR): seq[VkBuildAccelerationStructureFlagBitsKHR] = - for value in VkBuildAccelerationStructureFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkBuildAccelerationStructureFlagsKHR): bool = cint(a) == cint(b) -type - VkAccelerationStructureCreateFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0b00000000000000000000000000000001 - VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV = 0b00000000000000000000000000000100 - VK_ACCELERATION_STRUCTURE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkAccelerationStructureCreateFlagBitsKHR]): VkAccelerationStructureCreateFlagsKHR = - for flag in flags: - result = VkAccelerationStructureCreateFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkAccelerationStructureCreateFlagsKHR): seq[VkAccelerationStructureCreateFlagBitsKHR] = - for value in VkAccelerationStructureCreateFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkAccelerationStructureCreateFlagsKHR): bool = cint(a) == cint(b) -type - VkCopyAccelerationStructureModeKHR* {.size: sizeof(cint).} = enum - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR = 0 - VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR = 1 - VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR = 2 - VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR = 3 - VkBuildAccelerationStructureModeKHR* {.size: sizeof(cint).} = enum - VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR = 0 - VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR = 1 - VkAccelerationStructureTypeKHR* {.size: sizeof(cint).} = enum - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0 - VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1 - VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2 - VkGeometryTypeKHR* {.size: sizeof(cint).} = enum - VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0 - VK_GEOMETRY_TYPE_AABBS_KHR = 1 - VK_GEOMETRY_TYPE_INSTANCES_KHR = 2 - VkAccelerationStructureMemoryRequirementsTypeNV* {.size: sizeof(cint).} = enum - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0 - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1 - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2 - VkAccelerationStructureBuildTypeKHR* {.size: sizeof(cint).} = enum - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0 - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1 - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2 - VkRayTracingShaderGroupTypeKHR* {.size: sizeof(cint).} = enum - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR = 0 - VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR = 1 - VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR = 2 - VkAccelerationStructureCompatibilityKHR* {.size: sizeof(cint).} = enum - VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0 - VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR = 1 - VkShaderGroupShaderKHR* {.size: sizeof(cint).} = enum - VK_SHADER_GROUP_SHADER_GENERAL_KHR = 0 - VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR = 1 - VK_SHADER_GROUP_SHADER_ANY_HIT_KHR = 2 - VK_SHADER_GROUP_SHADER_INTERSECTION_KHR = 3 - VkMemoryOverallocationBehaviorAMD* {.size: sizeof(cint).} = enum - VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0 - VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1 - VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2 - VkFramebufferCreateFlagBits* {.size: sizeof(cint).} = enum - VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkFramebufferCreateFlagBits]): VkFramebufferCreateFlags = - for flag in flags: - result = VkFramebufferCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkFramebufferCreateFlags): seq[VkFramebufferCreateFlagBits] = - for value in VkFramebufferCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkFramebufferCreateFlags): bool = cint(a) == cint(b) -type - VkScopeNV* {.size: sizeof(cint).} = enum - VK_SCOPE_DEVICE_NV = 1 - VK_SCOPE_WORKGROUP_NV = 2 - VK_SCOPE_SUBGROUP_NV = 3 - VK_SCOPE_QUEUE_FAMILY_NV = 5 - VkComponentTypeNV* {.size: sizeof(cint).} = enum - VK_COMPONENT_TYPE_FLOAT16_NV = 0 - VK_COMPONENT_TYPE_FLOAT32_NV = 1 - VK_COMPONENT_TYPE_FLOAT64_NV = 2 - VK_COMPONENT_TYPE_SINT8_NV = 3 - VK_COMPONENT_TYPE_SINT16_NV = 4 - VK_COMPONENT_TYPE_SINT32_NV = 5 - VK_COMPONENT_TYPE_SINT64_NV = 6 - VK_COMPONENT_TYPE_UINT8_NV = 7 - VK_COMPONENT_TYPE_UINT16_NV = 8 - VK_COMPONENT_TYPE_UINT32_NV = 9 - VK_COMPONENT_TYPE_UINT64_NV = 10 - VkDeviceDiagnosticsConfigFlagBitsNV* {.size: sizeof(cint).} = enum - VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV = 0b00000000000000000000000000000001 - VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV = 0b00000000000000000000000000000010 - VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV = 0b00000000000000000000000000000100 - VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkDeviceDiagnosticsConfigFlagBitsNV]): VkDeviceDiagnosticsConfigFlagsNV = - for flag in flags: - result = VkDeviceDiagnosticsConfigFlagsNV(uint(result) or uint(flag)) -func toEnums*(number: VkDeviceDiagnosticsConfigFlagsNV): seq[VkDeviceDiagnosticsConfigFlagBitsNV] = - for value in VkDeviceDiagnosticsConfigFlagBitsNV.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDeviceDiagnosticsConfigFlagsNV): bool = cint(a) == cint(b) -type - VkPipelineCreationFeedbackFlagBits* {.size: sizeof(cint).} = enum - VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT = 0b00000000000000000000000000000001 - VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT = 0b00000000000000000000000000000010 - VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkPipelineCreationFeedbackFlagBits]): VkPipelineCreationFeedbackFlags = - for flag in flags: - result = VkPipelineCreationFeedbackFlags(uint(result) or uint(flag)) -func toEnums*(number: VkPipelineCreationFeedbackFlags): seq[VkPipelineCreationFeedbackFlagBits] = - for value in VkPipelineCreationFeedbackFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPipelineCreationFeedbackFlags): bool = cint(a) == cint(b) -type - VkFullScreenExclusiveEXT* {.size: sizeof(cint).} = enum - VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT = 0 - VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT = 1 - VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT = 2 - VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT = 3 - VkPerformanceCounterScopeKHR* {.size: sizeof(cint).} = enum - VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR = 0 - VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR = 1 - VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR = 2 - VkMemoryDecompressionMethodFlagBitsNV* {.size: 8.} = enum - VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV = 0b0000000000000000000000000000000000000000000000000000000000000001 -func toBits*(flags: openArray[VkMemoryDecompressionMethodFlagBitsNV]): VkMemoryDecompressionMethodFlagsNV = - for flag in flags: - result = VkMemoryDecompressionMethodFlagsNV(uint64(result) or uint64(flag)) -func toEnums*(number: VkMemoryDecompressionMethodFlagsNV): seq[VkMemoryDecompressionMethodFlagBitsNV] = - for value in VkMemoryDecompressionMethodFlagBitsNV.items: - if (cast[uint64](value) and uint64(number)) > 0: - result.add value -proc `==`*(a, b: VkMemoryDecompressionMethodFlagsNV): bool = uint64(a) == uint64(b) -type - VkPerformanceCounterUnitKHR* {.size: sizeof(cint).} = enum - VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR = 0 - VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR = 1 - VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR = 2 - VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR = 3 - VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR = 4 - VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR = 5 - VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR = 6 - VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR = 7 - VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR = 8 - VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR = 9 - VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR = 10 - VkPerformanceCounterStorageKHR* {.size: sizeof(cint).} = enum - VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR = 0 - VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR = 1 - VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR = 2 - VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR = 3 - VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR = 4 - VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR = 5 - VkPerformanceCounterDescriptionFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR = 0b00000000000000000000000000000001 - VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkPerformanceCounterDescriptionFlagBitsKHR]): VkPerformanceCounterDescriptionFlagsKHR = - for flag in flags: - result = VkPerformanceCounterDescriptionFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkPerformanceCounterDescriptionFlagsKHR): seq[VkPerformanceCounterDescriptionFlagBitsKHR] = - for value in VkPerformanceCounterDescriptionFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPerformanceCounterDescriptionFlagsKHR): bool = cint(a) == cint(b) -type - VkPerformanceConfigurationTypeINTEL* {.size: sizeof(cint).} = enum - VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL = 0 - VkQueryPoolSamplingModeINTEL* {.size: sizeof(cint).} = enum - VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL = 0 - VkPerformanceOverrideTypeINTEL* {.size: sizeof(cint).} = enum - VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL = 0 - VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL = 1 - VkPerformanceParameterTypeINTEL* {.size: sizeof(cint).} = enum - VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL = 0 - VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL = 1 - VkPerformanceValueTypeINTEL* {.size: sizeof(cint).} = enum - VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL = 0 - VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL = 1 - VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL = 2 - VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL = 3 - VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL = 4 - VkShaderFloatControlsIndependence* {.size: sizeof(cint).} = enum - VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY = 0 - VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL = 1 - VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE = 2 - VkPipelineExecutableStatisticFormatKHR* {.size: sizeof(cint).} = enum - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR = 0 - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR = 1 - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR = 2 - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR = 3 - VkLineRasterizationModeEXT* {.size: sizeof(cint).} = enum - VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT = 0 - VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT = 1 - VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT = 2 - VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT = 3 - VkFaultLevel* {.size: sizeof(cint).} = enum - VK_FAULT_LEVEL_UNASSIGNED = 0 - VK_FAULT_LEVEL_CRITICAL = 1 - VK_FAULT_LEVEL_RECOVERABLE = 2 - VK_FAULT_LEVEL_WARNING = 3 - VkFaultType* {.size: sizeof(cint).} = enum - VK_FAULT_TYPE_INVALID = 0 - VK_FAULT_TYPE_UNASSIGNED = 1 - VK_FAULT_TYPE_IMPLEMENTATION = 2 - VK_FAULT_TYPE_SYSTEM = 3 - VK_FAULT_TYPE_PHYSICAL_DEVICE = 4 - VK_FAULT_TYPE_COMMAND_BUFFER_FULL = 5 - VK_FAULT_TYPE_INVALID_API_USAGE = 6 - VkFaultQueryBehavior* {.size: sizeof(cint).} = enum - VK_FAULT_QUERY_BEHAVIOR_GET_AND_CLEAR_ALL_FAULTS = 0 - VkToolPurposeFlagBits* {.size: sizeof(cint).} = enum - VK_TOOL_PURPOSE_VALIDATION_BIT = 0b00000000000000000000000000000001 - VK_TOOL_PURPOSE_PROFILING_BIT = 0b00000000000000000000000000000010 - VK_TOOL_PURPOSE_TRACING_BIT = 0b00000000000000000000000000000100 - VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT = 0b00000000000000000000000000001000 - VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT = 0b00000000000000000000000000010000 - VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT = 0b00000000000000000000000000100000 - VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT = 0b00000000000000000000000001000000 -func toBits*(flags: openArray[VkToolPurposeFlagBits]): VkToolPurposeFlags = - for flag in flags: - result = VkToolPurposeFlags(uint(result) or uint(flag)) -func toEnums*(number: VkToolPurposeFlags): seq[VkToolPurposeFlagBits] = - for value in VkToolPurposeFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkToolPurposeFlags): bool = cint(a) == cint(b) -type - VkPipelineMatchControl* {.size: sizeof(cint).} = enum - VK_PIPELINE_MATCH_CONTROL_APPLICATION_UUID_EXACT_MATCH = 0 - VkFragmentShadingRateCombinerOpKHR* {.size: sizeof(cint).} = enum - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR = 0 - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR = 1 - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR = 2 - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR = 3 - VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR = 4 - VkFragmentShadingRateNV* {.size: sizeof(cint).} = enum - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV = 0 - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV = 1 - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV = 4 - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV = 5 - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV = 6 - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV = 9 - VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV = 10 - VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV = 11 - VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV = 12 - VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV = 13 - VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV = 14 - VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV = 15 - VkFragmentShadingRateTypeNV* {.size: sizeof(cint).} = enum - VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV = 0 - VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV = 1 - VkSubpassMergeStatusEXT* {.size: sizeof(cint).} = enum - VK_SUBPASS_MERGE_STATUS_MERGED_EXT = 0 - VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT = 1 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SIDE_EFFECTS_EXT = 2 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SAMPLES_MISMATCH_EXT = 3 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_VIEWS_MISMATCH_EXT = 4 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_ALIASING_EXT = 5 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPENDENCIES_EXT = 6 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INCOMPATIBLE_INPUT_ATTACHMENT_EXT = 7 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_TOO_MANY_ATTACHMENTS_EXT = 8 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INSUFFICIENT_STORAGE_EXT = 9 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPTH_STENCIL_COUNT_EXT = 10 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_RESOLVE_ATTACHMENT_REUSE_EXT = 11 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SINGLE_SUBPASS_EXT = 12 - VK_SUBPASS_MERGE_STATUS_NOT_MERGED_UNSPECIFIED_EXT = 13 - VkAccessFlagBits2* {.size: 8.} = enum - VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000000001 - VK_ACCESS_2_INDEX_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000000010 - VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000000100 - VK_ACCESS_2_UNIFORM_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000001000 - VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000010000 - VK_ACCESS_2_SHADER_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000000100000 - VK_ACCESS_2_SHADER_WRITE_BIT = 0b0000000000000000000000000000000000000000000000000000000001000000 - VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT = 0b0000000000000000000000000000000000000000000000000000000010000000 - VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT = 0b0000000000000000000000000000000000000000000000000000000100000000 - VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0b0000000000000000000000000000000000000000000000000000001000000000 - VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0b0000000000000000000000000000000000000000000000000000010000000000 - VK_ACCESS_2_TRANSFER_READ_BIT = 0b0000000000000000000000000000000000000000000000000000100000000000 - VK_ACCESS_2_TRANSFER_WRITE_BIT = 0b0000000000000000000000000000000000000000000000000001000000000000 - VK_ACCESS_2_HOST_READ_BIT = 0b0000000000000000000000000000000000000000000000000010000000000000 - VK_ACCESS_2_HOST_WRITE_BIT = 0b0000000000000000000000000000000000000000000000000100000000000000 - VK_ACCESS_2_MEMORY_READ_BIT = 0b0000000000000000000000000000000000000000000000001000000000000000 - VK_ACCESS_2_MEMORY_WRITE_BIT = 0b0000000000000000000000000000000000000000000000010000000000000000 - VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0b0000000000000000000000000000000000000000000000100000000000000000 - VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0b0000000000000000000000000000000000000000000001000000000000000000 - VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0b0000000000000000000000000000000000000000000010000000000000000000 - VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0b0000000000000000000000000000000000000000000100000000000000000000 - VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0b0000000000000000000000000000000000000000001000000000000000000000 - VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0b0000000000000000000000000000000000000000010000000000000000000000 - VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0b0000000000000000000000000000000000000000100000000000000000000000 - VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0b0000000000000000000000000000000000000001000000000000000000000000 - VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0b0000000000000000000000000000000000000010000000000000000000000000 - VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0b0000000000000000000000000000000000000100000000000000000000000000 - VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0b0000000000000000000000000000000000001000000000000000000000000000 - VK_ACCESS_2_SHADER_SAMPLED_READ_BIT = 0b0000000000000000000000000000000100000000000000000000000000000000 - VK_ACCESS_2_SHADER_STORAGE_READ_BIT = 0b0000000000000000000000000000001000000000000000000000000000000000 - VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT = 0b0000000000000000000000000000010000000000000000000000000000000000 - VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0b0000000000000000000000000000100000000000000000000000000000000000 - VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0b0000000000000000000000000001000000000000000000000000000000000000 - VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0b0000000000000000000000000010000000000000000000000000000000000000 - VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0b0000000000000000000000000100000000000000000000000000000000000000 - VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI = 0b0000000000000000000000001000000000000000000000000000000000000000 - VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR = 0b0000000000000000000000010000000000000000000000000000000000000000 - VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT = 0b0000000000000000000000100000000000000000000000000000000000000000 - VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV = 0b0000000000000000000001000000000000000000000000000000000000000000 - VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV = 0b0000000000000000000010000000000000000000000000000000000000000000 - VK_ACCESS_2_MICROMAP_READ_BIT_EXT = 0b0000000000000000000100000000000000000000000000000000000000000000 - VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT = 0b0000000000000000001000000000000000000000000000000000000000000000 - VK_ACCESS_2_RESERVED_46_BIT_EXT = 0b0000000000000000010000000000000000000000000000000000000000000000 -func toBits*(flags: openArray[VkAccessFlagBits2]): VkAccessFlags2 = - for flag in flags: - result = VkAccessFlags2(uint64(result) or uint64(flag)) -func toEnums*(number: VkAccessFlags2): seq[VkAccessFlagBits2] = - for value in VkAccessFlagBits2.items: - if (cast[uint64](value) and uint64(number)) > 0: - result.add value -proc `==`*(a, b: VkAccessFlags2): bool = uint64(a) == uint64(b) -const - VK_ACCESS_2_NONE* = 0 -type - VkPipelineStageFlagBits2* {.size: 8.} = enum - VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT = 0b0000000000000000000000000000000000000000000000000000000000000001 - VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT = 0b0000000000000000000000000000000000000000000000000000000000000010 - VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT = 0b0000000000000000000000000000000000000000000000000000000000000100 - VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000000000001000 - VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000000000010000 - VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000000000100000 - VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000000001000000 - VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000000010000000 - VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT = 0b0000000000000000000000000000000000000000000000000000000100000000 - VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT = 0b0000000000000000000000000000000000000000000000000000001000000000 - VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT = 0b0000000000000000000000000000000000000000000000000000010000000000 - VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT = 0b0000000000000000000000000000000000000000000000000000100000000000 - VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT = 0b0000000000000000000000000000000000000000000000000001000000000000 - VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT = 0b0000000000000000000000000000000000000000000000000010000000000000 - VK_PIPELINE_STAGE_2_HOST_BIT = 0b0000000000000000000000000000000000000000000000000100000000000000 - VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT = 0b0000000000000000000000000000000000000000000000001000000000000000 - VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT = 0b0000000000000000000000000000000000000000000000010000000000000000 - VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0b0000000000000000000000000000000000000000000000100000000000000000 - VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0b0000000000000000000000000000000000000000000001000000000000000000 - VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT = 0b0000000000000000000000000000000000000000000010000000000000000000 - VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT = 0b0000000000000000000000000000000000000000000100000000000000000000 - VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0b0000000000000000000000000000000000000000001000000000000000000000 - VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b0000000000000000000000000000000000000000010000000000000000000000 - VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0b0000000000000000000000000000000000000000100000000000000000000000 - VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0b0000000000000000000000000000000000000001000000000000000000000000 - VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0b0000000000000000000000000000000000000010000000000000000000000000 - VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR = 0b0000000000000000000000000000000000000100000000000000000000000000 - VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR = 0b0000000000000000000000000000000000001000000000000000000000000000 - VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR = 0b0000000000000000000000000000000000010000000000000000000000000000 - VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV = 0b0000000000000000000000000000000000100000000000000000000000000000 - VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT = 0b0000000000000000000000000000000001000000000000000000000000000000 - VK_PIPELINE_STAGE_2_COPY_BIT = 0b0000000000000000000000000000000100000000000000000000000000000000 - VK_PIPELINE_STAGE_2_RESOLVE_BIT = 0b0000000000000000000000000000001000000000000000000000000000000000 - VK_PIPELINE_STAGE_2_BLIT_BIT = 0b0000000000000000000000000000010000000000000000000000000000000000 - VK_PIPELINE_STAGE_2_CLEAR_BIT = 0b0000000000000000000000000000100000000000000000000000000000000000 - VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT = 0b0000000000000000000000000001000000000000000000000000000000000000 - VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT = 0b0000000000000000000000000010000000000000000000000000000000000000 - VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT = 0b0000000000000000000000000100000000000000000000000000000000000000 - VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0b0000000000000000000000001000000000000000000000000000000000000000 - VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0b0000000000000000000000010000000000000000000000000000000000000000 - VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI = 0b0000000000000000000000100000000000000000000000000000000000000000 -func toBits*(flags: openArray[VkPipelineStageFlagBits2]): VkPipelineStageFlags2 = - for flag in flags: - result = VkPipelineStageFlags2(uint64(result) or uint64(flag)) -func toEnums*(number: VkPipelineStageFlags2): seq[VkPipelineStageFlagBits2] = - for value in VkPipelineStageFlagBits2.items: - if (cast[uint64](value) and uint64(number)) > 0: - result.add value -proc `==`*(a, b: VkPipelineStageFlags2): bool = uint64(a) == uint64(b) -const - VK_PIPELINE_STAGE_2_NONE* = 0 -type - VkSubmitFlagBits* {.size: sizeof(cint).} = enum - VK_SUBMIT_PROTECTED_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkSubmitFlagBits]): VkSubmitFlags = - for flag in flags: - result = VkSubmitFlags(uint(result) or uint(flag)) -func toEnums*(number: VkSubmitFlags): seq[VkSubmitFlagBits] = - for value in VkSubmitFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkSubmitFlags): bool = cint(a) == cint(b) -type - VkEventCreateFlagBits* {.size: sizeof(cint).} = enum - VK_EVENT_CREATE_DEVICE_ONLY_BIT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkEventCreateFlagBits]): VkEventCreateFlags = - for flag in flags: - result = VkEventCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkEventCreateFlags): seq[VkEventCreateFlagBits] = - for value in VkEventCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkEventCreateFlags): bool = cint(a) == cint(b) -type - VkPipelineLayoutCreateFlagBits* {.size: sizeof(cint).} = enum - VK_PIPELINE_LAYOUT_CREATE_RESERVED_0_BIT_AMD = 0b00000000000000000000000000000001 - VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkPipelineLayoutCreateFlagBits]): VkPipelineLayoutCreateFlags = - for flag in flags: - result = VkPipelineLayoutCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkPipelineLayoutCreateFlags): seq[VkPipelineLayoutCreateFlagBits] = - for value in VkPipelineLayoutCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPipelineLayoutCreateFlags): bool = cint(a) == cint(b) -type - VkSciSyncClientTypeNV* {.size: sizeof(cint).} = enum - VK_SCI_SYNC_CLIENT_TYPE_SIGNALER_NV = 0 - VK_SCI_SYNC_CLIENT_TYPE_WAITER_NV = 1 - VK_SCI_SYNC_CLIENT_TYPE_SIGNALER_WAITER_NV = 2 - VkSciSyncPrimitiveTypeNV* {.size: sizeof(cint).} = enum - VK_SCI_SYNC_PRIMITIVE_TYPE_FENCE_NV = 0 - VK_SCI_SYNC_PRIMITIVE_TYPE_SEMAPHORE_NV = 1 - VkProvokingVertexModeEXT* {.size: sizeof(cint).} = enum - VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT = 0 - VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT = 1 - VkPipelineCacheValidationVersion* {.size: sizeof(cint).} = enum - VK_PIPELINE_CACHE_VALIDATION_VERSION_SAFETY_CRITICAL_ONE = 1 - VkAccelerationStructureMotionInstanceTypeNV* {.size: sizeof(cint).} = enum - VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV = 0 - VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV = 1 - VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV = 2 - VkPipelineColorBlendStateCreateFlagBits* {.size: sizeof(cint).} = enum - VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkPipelineColorBlendStateCreateFlagBits]): VkPipelineColorBlendStateCreateFlags = - for flag in flags: - result = VkPipelineColorBlendStateCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkPipelineColorBlendStateCreateFlags): seq[VkPipelineColorBlendStateCreateFlagBits] = - for value in VkPipelineColorBlendStateCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPipelineColorBlendStateCreateFlags): bool = cint(a) == cint(b) -type - VkPipelineDepthStencilStateCreateFlagBits* {.size: sizeof(cint).} = enum - VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0b00000000000000000000000000000001 - VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkPipelineDepthStencilStateCreateFlagBits]): VkPipelineDepthStencilStateCreateFlags = - for flag in flags: - result = VkPipelineDepthStencilStateCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkPipelineDepthStencilStateCreateFlags): seq[VkPipelineDepthStencilStateCreateFlagBits] = - for value in VkPipelineDepthStencilStateCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPipelineDepthStencilStateCreateFlags): bool = cint(a) == cint(b) -type - VkGraphicsPipelineLibraryFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT = 0b00000000000000000000000000000001 - VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT = 0b00000000000000000000000000000010 - VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT = 0b00000000000000000000000000000100 - VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkGraphicsPipelineLibraryFlagBitsEXT]): VkGraphicsPipelineLibraryFlagsEXT = - for flag in flags: - result = VkGraphicsPipelineLibraryFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkGraphicsPipelineLibraryFlagsEXT): seq[VkGraphicsPipelineLibraryFlagBitsEXT] = - for value in VkGraphicsPipelineLibraryFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkGraphicsPipelineLibraryFlagsEXT): bool = cint(a) == cint(b) -type - VkDeviceAddressBindingFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_DEVICE_ADDRESS_BINDING_INTERNAL_OBJECT_BIT_EXT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkDeviceAddressBindingFlagBitsEXT]): VkDeviceAddressBindingFlagsEXT = - for flag in flags: - result = VkDeviceAddressBindingFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkDeviceAddressBindingFlagsEXT): seq[VkDeviceAddressBindingFlagBitsEXT] = - for value in VkDeviceAddressBindingFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkDeviceAddressBindingFlagsEXT): bool = cint(a) == cint(b) -type - VkDeviceAddressBindingTypeEXT* {.size: sizeof(cint).} = enum - VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT = 0 - VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT = 1 - VkPresentScalingFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT = 0b00000000000000000000000000000001 - VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT = 0b00000000000000000000000000000010 - VK_PRESENT_SCALING_STRETCH_BIT_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkPresentScalingFlagBitsEXT]): VkPresentScalingFlagsEXT = - for flag in flags: - result = VkPresentScalingFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkPresentScalingFlagsEXT): seq[VkPresentScalingFlagBitsEXT] = - for value in VkPresentScalingFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPresentScalingFlagsEXT): bool = cint(a) == cint(b) -type - VkPresentGravityFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_PRESENT_GRAVITY_MIN_BIT_EXT = 0b00000000000000000000000000000001 - VK_PRESENT_GRAVITY_MAX_BIT_EXT = 0b00000000000000000000000000000010 - VK_PRESENT_GRAVITY_CENTERED_BIT_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkPresentGravityFlagBitsEXT]): VkPresentGravityFlagsEXT = - for flag in flags: - result = VkPresentGravityFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkPresentGravityFlagsEXT): seq[VkPresentGravityFlagBitsEXT] = - for value in VkPresentGravityFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkPresentGravityFlagsEXT): bool = cint(a) == cint(b) -type - VkVideoCodecOperationFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR = 0b00000000000000000000000000000010 - VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT = 0b00000000000000010000000000000000 - VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT = 0b00000000000000100000000000000000 -func toBits*(flags: openArray[VkVideoCodecOperationFlagBitsKHR]): VkVideoCodecOperationFlagsKHR = - for flag in flags: - result = VkVideoCodecOperationFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoCodecOperationFlagsKHR): seq[VkVideoCodecOperationFlagBitsKHR] = - for value in VkVideoCodecOperationFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoCodecOperationFlagsKHR): bool = cint(a) == cint(b) -const - VK_VIDEO_CODEC_OPERATION_NONE_KHR* = 0 -type - VkVideoChromaSubsamplingFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR = 0b00000000000000000000000000000010 - VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR = 0b00000000000000000000000000000100 - VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkVideoChromaSubsamplingFlagBitsKHR]): VkVideoChromaSubsamplingFlagsKHR = - for flag in flags: - result = VkVideoChromaSubsamplingFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoChromaSubsamplingFlagsKHR): seq[VkVideoChromaSubsamplingFlagBitsKHR] = - for value in VkVideoChromaSubsamplingFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoChromaSubsamplingFlagsKHR): bool = cint(a) == cint(b) -const - VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR* = 0 -type - VkVideoComponentBitDepthFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR = 0b00000000000000000000000000000100 - VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR = 0b00000000000000000000000000010000 -func toBits*(flags: openArray[VkVideoComponentBitDepthFlagBitsKHR]): VkVideoComponentBitDepthFlagsKHR = - for flag in flags: - result = VkVideoComponentBitDepthFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoComponentBitDepthFlagsKHR): seq[VkVideoComponentBitDepthFlagBitsKHR] = - for value in VkVideoComponentBitDepthFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoComponentBitDepthFlagsKHR): bool = cint(a) == cint(b) -const - VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR* = 0 -type - VkVideoCapabilityFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkVideoCapabilityFlagBitsKHR]): VkVideoCapabilityFlagsKHR = - for flag in flags: - result = VkVideoCapabilityFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoCapabilityFlagsKHR): seq[VkVideoCapabilityFlagBitsKHR] = - for value in VkVideoCapabilityFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoCapabilityFlagsKHR): bool = cint(a) == cint(b) -type - VkVideoSessionCreateFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkVideoSessionCreateFlagBitsKHR]): VkVideoSessionCreateFlagsKHR = - for flag in flags: - result = VkVideoSessionCreateFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoSessionCreateFlagsKHR): seq[VkVideoSessionCreateFlagBitsKHR] = - for value in VkVideoSessionCreateFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoSessionCreateFlagsKHR): bool = cint(a) == cint(b) -type - VkVideoDecodeH264PictureLayoutFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_KHR = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkVideoDecodeH264PictureLayoutFlagBitsKHR]): VkVideoDecodeH264PictureLayoutFlagsKHR = - for flag in flags: - result = VkVideoDecodeH264PictureLayoutFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoDecodeH264PictureLayoutFlagsKHR): seq[VkVideoDecodeH264PictureLayoutFlagBitsKHR] = - for value in VkVideoDecodeH264PictureLayoutFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoDecodeH264PictureLayoutFlagsKHR): bool = cint(a) == cint(b) -const - VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR* = 0 -type - VkVideoCodingControlFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR = 0b00000000000000000000000000000010 - VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_LAYER_BIT_KHR = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkVideoCodingControlFlagBitsKHR]): VkVideoCodingControlFlagsKHR = - for flag in flags: - result = VkVideoCodingControlFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoCodingControlFlagsKHR): seq[VkVideoCodingControlFlagBitsKHR] = - for value in VkVideoCodingControlFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoCodingControlFlagsKHR): bool = cint(a) == cint(b) -type - VkQueryResultStatusKHR* {.size: sizeof(cint).} = enum - VK_QUERY_RESULT_STATUS_ERROR_KHR = -1 - VK_QUERY_RESULT_STATUS_NOT_READY_KHR = 0 - VK_QUERY_RESULT_STATUS_COMPLETE_KHR = 1 - VkVideoDecodeUsageFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_DECODE_USAGE_TRANSCODING_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_DECODE_USAGE_OFFLINE_BIT_KHR = 0b00000000000000000000000000000010 - VK_VIDEO_DECODE_USAGE_STREAMING_BIT_KHR = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkVideoDecodeUsageFlagBitsKHR]): VkVideoDecodeUsageFlagsKHR = - for flag in flags: - result = VkVideoDecodeUsageFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoDecodeUsageFlagsKHR): seq[VkVideoDecodeUsageFlagBitsKHR] = - for value in VkVideoDecodeUsageFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoDecodeUsageFlagsKHR): bool = cint(a) == cint(b) -const - VK_VIDEO_DECODE_USAGE_DEFAULT_KHR* = 0 -type - VkVideoDecodeCapabilityFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR = 0b00000000000000000000000000000010 -func toBits*(flags: openArray[VkVideoDecodeCapabilityFlagBitsKHR]): VkVideoDecodeCapabilityFlagsKHR = - for flag in flags: - result = VkVideoDecodeCapabilityFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoDecodeCapabilityFlagsKHR): seq[VkVideoDecodeCapabilityFlagBitsKHR] = - for value in VkVideoDecodeCapabilityFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoDecodeCapabilityFlagsKHR): bool = cint(a) == cint(b) -type - VkVideoEncodeUsageFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_USAGE_STREAMING_BIT_KHR = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_USAGE_RECORDING_BIT_KHR = 0b00000000000000000000000000000100 - VK_VIDEO_ENCODE_USAGE_CONFERENCING_BIT_KHR = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkVideoEncodeUsageFlagBitsKHR]): VkVideoEncodeUsageFlagsKHR = - for flag in flags: - result = VkVideoEncodeUsageFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeUsageFlagsKHR): seq[VkVideoEncodeUsageFlagBitsKHR] = - for value in VkVideoEncodeUsageFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeUsageFlagsKHR): bool = cint(a) == cint(b) -const - VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR* = 0 -type - VkVideoEncodeContentFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_CONTENT_CAMERA_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_CONTENT_DESKTOP_BIT_KHR = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_CONTENT_RENDERED_BIT_KHR = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkVideoEncodeContentFlagBitsKHR]): VkVideoEncodeContentFlagsKHR = - for flag in flags: - result = VkVideoEncodeContentFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeContentFlagsKHR): seq[VkVideoEncodeContentFlagBitsKHR] = - for value in VkVideoEncodeContentFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeContentFlagsKHR): bool = cint(a) == cint(b) -const - VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR* = 0 -type - VkVideoEncodeTuningModeKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR = 0 - VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR = 1 - VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR = 2 - VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR = 3 - VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR = 4 - VkVideoEncodeCapabilityFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkVideoEncodeCapabilityFlagBitsKHR]): VkVideoEncodeCapabilityFlagsKHR = - for flag in flags: - result = VkVideoEncodeCapabilityFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeCapabilityFlagsKHR): seq[VkVideoEncodeCapabilityFlagBitsKHR] = - for value in VkVideoEncodeCapabilityFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeCapabilityFlagsKHR): bool = cint(a) == cint(b) -type - VkVideoEncodeRateControlModeFlagBitsKHR* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkVideoEncodeRateControlModeFlagBitsKHR]): VkVideoEncodeRateControlModeFlagsKHR = - for flag in flags: - result = VkVideoEncodeRateControlModeFlagsKHR(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeRateControlModeFlagsKHR): seq[VkVideoEncodeRateControlModeFlagBitsKHR] = - for value in VkVideoEncodeRateControlModeFlagBitsKHR.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeRateControlModeFlagsKHR): bool = cint(a) == cint(b) -type - VkVideoEncodeH264CapabilityFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_ENABLED_BIT_EXT = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_DISABLED_BIT_EXT = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_H264_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT = 0b00000000000000000000000000000100 - VK_VIDEO_ENCODE_H264_CAPABILITY_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_BIT_EXT = 0b00000000000000000000000000001000 - VK_VIDEO_ENCODE_H264_CAPABILITY_SCALING_LISTS_BIT_EXT = 0b00000000000000000000000000010000 - VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_EXT = 0b00000000000000000000000000100000 - VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT = 0b00000000000000000000000001000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT = 0b00000000000000000000000010000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_PIC_INIT_QP_MINUS26_BIT_EXT = 0b00000000000000000000000100000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_BIT_EXT = 0b00000000000000000000001000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_EXPLICIT_BIT_EXT = 0b00000000000000000000010000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_IMPLICIT_BIT_EXT = 0b00000000000000000000100000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT = 0b00000000000000000001000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT = 0b00000000000000000010000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT = 0b00000000000000000100000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT = 0b00000000000000001000000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT = 0b00000000000000010000000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT = 0b00000000000000100000000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT = 0b00000000000001000000000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_DISABLE_DIRECT_SPATIAL_MV_PRED_BIT_EXT = 0b00000000000010000000000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT = 0b00000000000100000000000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_SLICE_MB_COUNT_BIT_EXT = 0b00000000001000000000000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_EXT = 0b00000000010000000000000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT = 0b00000000100000000000000000000000 - VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0b00000001000000000000000000000000 -func toBits*(flags: openArray[VkVideoEncodeH264CapabilityFlagBitsEXT]): VkVideoEncodeH264CapabilityFlagsEXT = - for flag in flags: - result = VkVideoEncodeH264CapabilityFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeH264CapabilityFlagsEXT): seq[VkVideoEncodeH264CapabilityFlagBitsEXT] = - for value in VkVideoEncodeH264CapabilityFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeH264CapabilityFlagsEXT): bool = cint(a) == cint(b) -type - VkVideoEncodeH264InputModeFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkVideoEncodeH264InputModeFlagBitsEXT]): VkVideoEncodeH264InputModeFlagsEXT = - for flag in flags: - result = VkVideoEncodeH264InputModeFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeH264InputModeFlagsEXT): seq[VkVideoEncodeH264InputModeFlagBitsEXT] = - for value in VkVideoEncodeH264InputModeFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeH264InputModeFlagsEXT): bool = cint(a) == cint(b) -type - VkVideoEncodeH264OutputModeFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkVideoEncodeH264OutputModeFlagBitsEXT]): VkVideoEncodeH264OutputModeFlagsEXT = - for flag in flags: - result = VkVideoEncodeH264OutputModeFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeH264OutputModeFlagsEXT): seq[VkVideoEncodeH264OutputModeFlagBitsEXT] = - for value in VkVideoEncodeH264OutputModeFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeH264OutputModeFlagsEXT): bool = cint(a) == cint(b) -type - VkVideoEncodeH264RateControlStructureEXT* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT = 0 - VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_FLAT_EXT = 1 - VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_DYADIC_EXT = 2 - VkImageConstraintsInfoFlagBitsFUCHSIA* {.size: sizeof(cint).} = enum - VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA = 0b00000000000000000000000000000001 - VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA = 0b00000000000000000000000000000010 - VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA = 0b00000000000000000000000000000100 - VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA = 0b00000000000000000000000000001000 - VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA = 0b00000000000000000000000000010000 -func toBits*(flags: openArray[VkImageConstraintsInfoFlagBitsFUCHSIA]): VkImageConstraintsInfoFlagsFUCHSIA = - for flag in flags: - result = VkImageConstraintsInfoFlagsFUCHSIA(uint(result) or uint(flag)) -func toEnums*(number: VkImageConstraintsInfoFlagsFUCHSIA): seq[VkImageConstraintsInfoFlagBitsFUCHSIA] = - for value in VkImageConstraintsInfoFlagBitsFUCHSIA.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkImageConstraintsInfoFlagsFUCHSIA): bool = cint(a) == cint(b) -type - VkFormatFeatureFlagBits2* {.size: 8.} = enum - VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT = 0b0000000000000000000000000000000000000000000000000000000000000001 - VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT = 0b0000000000000000000000000000000000000000000000000000000000000010 - VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT = 0b0000000000000000000000000000000000000000000000000000000000000100 - VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT = 0b0000000000000000000000000000000000000000000000000000000000001000 - VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT = 0b0000000000000000000000000000000000000000000000000000000000010000 - VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0b0000000000000000000000000000000000000000000000000000000000100000 - VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT = 0b0000000000000000000000000000000000000000000000000000000001000000 - VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT = 0b0000000000000000000000000000000000000000000000000000000010000000 - VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT = 0b0000000000000000000000000000000000000000000000000000000100000000 - VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT = 0b0000000000000000000000000000000000000000000000000000001000000000 - VK_FORMAT_FEATURE_2_BLIT_SRC_BIT = 0b0000000000000000000000000000000000000000000000000000010000000000 - VK_FORMAT_FEATURE_2_BLIT_DST_BIT = 0b0000000000000000000000000000000000000000000000000000100000000000 - VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0b0000000000000000000000000000000000000000000000000001000000000000 - VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT = 0b0000000000000000000000000000000000000000000000000010000000000000 - VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT = 0b0000000000000000000000000000000000000000000000000100000000000000 - VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT = 0b0000000000000000000000000000000000000000000000001000000000000000 - VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0b0000000000000000000000000000000000000000000000010000000000000000 - VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT = 0b0000000000000000000000000000000000000000000000100000000000000000 - VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0b0000000000000000000000000000000000000000000001000000000000000000 - VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0b0000000000000000000000000000000000000000000010000000000000000000 - VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0b0000000000000000000000000000000000000000000100000000000000000000 - VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0b0000000000000000000000000000000000000000001000000000000000000000 - VK_FORMAT_FEATURE_2_DISJOINT_BIT = 0b0000000000000000000000000000000000000000010000000000000000000000 - VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT = 0b0000000000000000000000000000000000000000100000000000000000000000 - VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT = 0b0000000000000000000000000000000000000001000000000000000000000000 - VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR = 0b0000000000000000000000000000000000000010000000000000000000000000 - VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR = 0b0000000000000000000000000000000000000100000000000000000000000000 - VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR = 0b0000000000000000000000000000000000001000000000000000000000000000 - VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR = 0b0000000000000000000000000000000000010000000000000000000000000000 - VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0b0000000000000000000000000000000000100000000000000000000000000000 - VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0b0000000000000000000000000000000001000000000000000000000000000000 - VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT = 0b0000000000000000000000000000000010000000000000000000000000000000 - VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT = 0b0000000000000000000000000000000100000000000000000000000000000000 - VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT = 0b0000000000000000000000000000001000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM = 0b0000000000000000000000000000010000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM = 0b0000000000000000000000000000100000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM = 0b0000000000000000000000000001000000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM = 0b0000000000000000000000000010000000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV = 0b0000000000000000000000000100000000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_RESERVED_39_BIT_EXT = 0b0000000000000000000000001000000000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV = 0b0000000000000000000000010000000000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV = 0b0000000000000000000000100000000000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV = 0b0000000000000000000001000000000000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_RESERVED_44_BIT_EXT = 0b0000000000000000000100000000000000000000000000000000000000000000 - VK_FORMAT_FEATURE_2_RESERVED_45_BIT_EXT = 0b0000000000000000001000000000000000000000000000000000000000000000 -func toBits*(flags: openArray[VkFormatFeatureFlagBits2]): VkFormatFeatureFlags2 = - for flag in flags: - result = VkFormatFeatureFlags2(uint64(result) or uint64(flag)) -func toEnums*(number: VkFormatFeatureFlags2): seq[VkFormatFeatureFlagBits2] = - for value in VkFormatFeatureFlagBits2.items: - if (cast[uint64](value) and uint64(number)) > 0: - result.add value -proc `==`*(a, b: VkFormatFeatureFlags2): bool = uint64(a) == uint64(b) -type - VkRenderingFlagBits* {.size: sizeof(cint).} = enum - VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT = 0b00000000000000000000000000000001 - VK_RENDERING_SUSPENDING_BIT = 0b00000000000000000000000000000010 - VK_RENDERING_RESUMING_BIT = 0b00000000000000000000000000000100 - VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkRenderingFlagBits]): VkRenderingFlags = - for flag in flags: - result = VkRenderingFlags(uint(result) or uint(flag)) -func toEnums*(number: VkRenderingFlags): seq[VkRenderingFlagBits] = - for value in VkRenderingFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkRenderingFlags): bool = cint(a) == cint(b) -type - VkVideoEncodeH265CapabilityFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_H265_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_H265_CAPABILITY_SCALING_LISTS_BIT_EXT = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_H265_CAPABILITY_SAMPLE_ADAPTIVE_OFFSET_ENABLED_BIT_EXT = 0b00000000000000000000000000000100 - VK_VIDEO_ENCODE_H265_CAPABILITY_PCM_ENABLE_BIT_EXT = 0b00000000000000000000000000001000 - VK_VIDEO_ENCODE_H265_CAPABILITY_SPS_TEMPORAL_MVP_ENABLED_BIT_EXT = 0b00000000000000000000000000010000 - VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_EXT = 0b00000000000000000000000000100000 - VK_VIDEO_ENCODE_H265_CAPABILITY_INIT_QP_MINUS26_BIT_EXT = 0b00000000000000000000000001000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_EXT = 0b00000000000000000000000010000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_SIGN_DATA_HIDING_ENABLED_BIT_EXT = 0b00000000000000000000000100000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_ENABLED_BIT_EXT = 0b00000000000000000000001000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_DISABLED_BIT_EXT = 0b00000000000000000000010000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_BIT_EXT = 0b00000000000000000000100000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_BIT_EXT = 0b00000000000000000001000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_BIPRED_BIT_EXT = 0b00000000000000000010000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT = 0b00000000000000000100000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSQUANT_BYPASS_ENABLED_BIT_EXT = 0b00000000000000001000000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_ENTROPY_CODING_SYNC_ENABLED_BIT_EXT = 0b00000000000000010000000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_DEBLOCKING_FILTER_OVERRIDE_ENABLED_BIT_EXT = 0b00000000000000100000000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_FRAME_BIT_EXT = 0b00000000000001000000000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_PER_TILE_BIT_EXT = 0b00000000000010000000000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_SLICE_BIT_EXT = 0b00000000000100000000000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_SLICE_SEGMENT_CTB_COUNT_BIT_EXT = 0b00000000001000000000000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_EXT = 0b00000000010000000000000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_DEPENDENT_SLICE_SEGMENT_BIT_EXT = 0b00000000100000000000000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT = 0b00000001000000000000000000000000 - VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0b00000010000000000000000000000000 -func toBits*(flags: openArray[VkVideoEncodeH265CapabilityFlagBitsEXT]): VkVideoEncodeH265CapabilityFlagsEXT = - for flag in flags: - result = VkVideoEncodeH265CapabilityFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeH265CapabilityFlagsEXT): seq[VkVideoEncodeH265CapabilityFlagBitsEXT] = - for value in VkVideoEncodeH265CapabilityFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeH265CapabilityFlagsEXT): bool = cint(a) == cint(b) -type - VkVideoEncodeH265InputModeFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_H265_INPUT_MODE_FRAME_BIT_EXT = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_H265_INPUT_MODE_SLICE_SEGMENT_BIT_EXT = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_H265_INPUT_MODE_NON_VCL_BIT_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkVideoEncodeH265InputModeFlagBitsEXT]): VkVideoEncodeH265InputModeFlagsEXT = - for flag in flags: - result = VkVideoEncodeH265InputModeFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeH265InputModeFlagsEXT): seq[VkVideoEncodeH265InputModeFlagBitsEXT] = - for value in VkVideoEncodeH265InputModeFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeH265InputModeFlagsEXT): bool = cint(a) == cint(b) -type - VkVideoEncodeH265OutputModeFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FRAME_BIT_EXT = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_H265_OUTPUT_MODE_SLICE_SEGMENT_BIT_EXT = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_H265_OUTPUT_MODE_NON_VCL_BIT_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkVideoEncodeH265OutputModeFlagBitsEXT]): VkVideoEncodeH265OutputModeFlagsEXT = - for flag in flags: - result = VkVideoEncodeH265OutputModeFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeH265OutputModeFlagsEXT): seq[VkVideoEncodeH265OutputModeFlagBitsEXT] = - for value in VkVideoEncodeH265OutputModeFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeH265OutputModeFlagsEXT): bool = cint(a) == cint(b) -type - VkVideoEncodeH265RateControlStructureEXT* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT = 0 - VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_FLAT_EXT = 1 - VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_DYADIC_EXT = 2 - VkVideoEncodeH265CtbSizeFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_EXT = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkVideoEncodeH265CtbSizeFlagBitsEXT]): VkVideoEncodeH265CtbSizeFlagsEXT = - for flag in flags: - result = VkVideoEncodeH265CtbSizeFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeH265CtbSizeFlagsEXT): seq[VkVideoEncodeH265CtbSizeFlagBitsEXT] = - for value in VkVideoEncodeH265CtbSizeFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeH265CtbSizeFlagsEXT): bool = cint(a) == cint(b) -type - VkVideoEncodeH265TransformBlockSizeFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_EXT = 0b00000000000000000000000000000001 - VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_EXT = 0b00000000000000000000000000000010 - VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_EXT = 0b00000000000000000000000000000100 - VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_EXT = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkVideoEncodeH265TransformBlockSizeFlagBitsEXT]): VkVideoEncodeH265TransformBlockSizeFlagsEXT = - for flag in flags: - result = VkVideoEncodeH265TransformBlockSizeFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkVideoEncodeH265TransformBlockSizeFlagsEXT): seq[VkVideoEncodeH265TransformBlockSizeFlagBitsEXT] = - for value in VkVideoEncodeH265TransformBlockSizeFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkVideoEncodeH265TransformBlockSizeFlagsEXT): bool = cint(a) == cint(b) -type - VkExportMetalObjectTypeFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT = 0b00000000000000000000000000000001 - VK_EXPORT_METAL_OBJECT_TYPE_METAL_COMMAND_QUEUE_BIT_EXT = 0b00000000000000000000000000000010 - VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT = 0b00000000000000000000000000000100 - VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT = 0b00000000000000000000000000001000 - VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT = 0b00000000000000000000000000010000 - VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT = 0b00000000000000000000000000100000 -func toBits*(flags: openArray[VkExportMetalObjectTypeFlagBitsEXT]): VkExportMetalObjectTypeFlagsEXT = - for flag in flags: - result = VkExportMetalObjectTypeFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkExportMetalObjectTypeFlagsEXT): seq[VkExportMetalObjectTypeFlagBitsEXT] = - for value in VkExportMetalObjectTypeFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkExportMetalObjectTypeFlagsEXT): bool = cint(a) == cint(b) -type - VkInstanceCreateFlagBits* {.size: sizeof(cint).} = enum - VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkInstanceCreateFlagBits]): VkInstanceCreateFlags = - for flag in flags: - result = VkInstanceCreateFlags(uint(result) or uint(flag)) -func toEnums*(number: VkInstanceCreateFlags): seq[VkInstanceCreateFlagBits] = - for value in VkInstanceCreateFlagBits.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkInstanceCreateFlags): bool = cint(a) == cint(b) -type - VkImageCompressionFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT = 0b00000000000000000000000000000001 - VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT = 0b00000000000000000000000000000010 - VK_IMAGE_COMPRESSION_DISABLED_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkImageCompressionFlagBitsEXT]): VkImageCompressionFlagsEXT = - for flag in flags: - result = VkImageCompressionFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkImageCompressionFlagsEXT): seq[VkImageCompressionFlagBitsEXT] = - for value in VkImageCompressionFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkImageCompressionFlagsEXT): bool = cint(a) == cint(b) -const - VK_IMAGE_COMPRESSION_DEFAULT_EXT* = 0 -type - VkImageCompressionFixedRateFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_IMAGE_COMPRESSION_FIXED_RATE_1BPC_BIT_EXT = 0b00000000000000000000000000000001 - VK_IMAGE_COMPRESSION_FIXED_RATE_2BPC_BIT_EXT = 0b00000000000000000000000000000010 - VK_IMAGE_COMPRESSION_FIXED_RATE_3BPC_BIT_EXT = 0b00000000000000000000000000000100 - VK_IMAGE_COMPRESSION_FIXED_RATE_4BPC_BIT_EXT = 0b00000000000000000000000000001000 - VK_IMAGE_COMPRESSION_FIXED_RATE_5BPC_BIT_EXT = 0b00000000000000000000000000010000 - VK_IMAGE_COMPRESSION_FIXED_RATE_6BPC_BIT_EXT = 0b00000000000000000000000000100000 - VK_IMAGE_COMPRESSION_FIXED_RATE_7BPC_BIT_EXT = 0b00000000000000000000000001000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_8BPC_BIT_EXT = 0b00000000000000000000000010000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_9BPC_BIT_EXT = 0b00000000000000000000000100000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_10BPC_BIT_EXT = 0b00000000000000000000001000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_11BPC_BIT_EXT = 0b00000000000000000000010000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_12BPC_BIT_EXT = 0b00000000000000000000100000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_13BPC_BIT_EXT = 0b00000000000000000001000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_14BPC_BIT_EXT = 0b00000000000000000010000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_15BPC_BIT_EXT = 0b00000000000000000100000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_16BPC_BIT_EXT = 0b00000000000000001000000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_17BPC_BIT_EXT = 0b00000000000000010000000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_18BPC_BIT_EXT = 0b00000000000000100000000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_19BPC_BIT_EXT = 0b00000000000001000000000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_20BPC_BIT_EXT = 0b00000000000010000000000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_21BPC_BIT_EXT = 0b00000000000100000000000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_22BPC_BIT_EXT = 0b00000000001000000000000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_23BPC_BIT_EXT = 0b00000000010000000000000000000000 - VK_IMAGE_COMPRESSION_FIXED_RATE_24BPC_BIT_EXT = 0b00000000100000000000000000000000 -func toBits*(flags: openArray[VkImageCompressionFixedRateFlagBitsEXT]): VkImageCompressionFixedRateFlagsEXT = - for flag in flags: - result = VkImageCompressionFixedRateFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkImageCompressionFixedRateFlagsEXT): seq[VkImageCompressionFixedRateFlagBitsEXT] = - for value in VkImageCompressionFixedRateFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkImageCompressionFixedRateFlagsEXT): bool = cint(a) == cint(b) -const - VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT* = 0 -type - VkPipelineRobustnessBufferBehaviorEXT* {.size: sizeof(cint).} = enum - VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT = 0 - VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT = 1 - VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT = 2 - VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT = 3 - VkPipelineRobustnessImageBehaviorEXT* {.size: sizeof(cint).} = enum - VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT = 0 - VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT = 1 - VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_EXT = 2 - VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2_EXT = 3 - VkOpticalFlowGridSizeFlagBitsNV* {.size: sizeof(cint).} = enum - VK_OPTICAL_FLOW_GRID_SIZE_1X1_BIT_NV = 0b00000000000000000000000000000001 - VK_OPTICAL_FLOW_GRID_SIZE_2X2_BIT_NV = 0b00000000000000000000000000000010 - VK_OPTICAL_FLOW_GRID_SIZE_4X4_BIT_NV = 0b00000000000000000000000000000100 - VK_OPTICAL_FLOW_GRID_SIZE_8X8_BIT_NV = 0b00000000000000000000000000001000 -func toBits*(flags: openArray[VkOpticalFlowGridSizeFlagBitsNV]): VkOpticalFlowGridSizeFlagsNV = - for flag in flags: - result = VkOpticalFlowGridSizeFlagsNV(uint(result) or uint(flag)) -func toEnums*(number: VkOpticalFlowGridSizeFlagsNV): seq[VkOpticalFlowGridSizeFlagBitsNV] = - for value in VkOpticalFlowGridSizeFlagBitsNV.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkOpticalFlowGridSizeFlagsNV): bool = cint(a) == cint(b) -const - VK_OPTICAL_FLOW_GRID_SIZE_UNKNOWN_NV* = 0 -type - VkOpticalFlowUsageFlagBitsNV* {.size: sizeof(cint).} = enum - VK_OPTICAL_FLOW_USAGE_INPUT_BIT_NV = 0b00000000000000000000000000000001 - VK_OPTICAL_FLOW_USAGE_OUTPUT_BIT_NV = 0b00000000000000000000000000000010 - VK_OPTICAL_FLOW_USAGE_HINT_BIT_NV = 0b00000000000000000000000000000100 - VK_OPTICAL_FLOW_USAGE_COST_BIT_NV = 0b00000000000000000000000000001000 - VK_OPTICAL_FLOW_USAGE_GLOBAL_FLOW_BIT_NV = 0b00000000000000000000000000010000 -func toBits*(flags: openArray[VkOpticalFlowUsageFlagBitsNV]): VkOpticalFlowUsageFlagsNV = - for flag in flags: - result = VkOpticalFlowUsageFlagsNV(uint(result) or uint(flag)) -func toEnums*(number: VkOpticalFlowUsageFlagsNV): seq[VkOpticalFlowUsageFlagBitsNV] = - for value in VkOpticalFlowUsageFlagBitsNV.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkOpticalFlowUsageFlagsNV): bool = cint(a) == cint(b) -const - VK_OPTICAL_FLOW_USAGE_UNKNOWN_NV* = 0 -type - VkOpticalFlowPerformanceLevelNV* {.size: sizeof(cint).} = enum - VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_UNKNOWN_NV = 0 - VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_SLOW_NV = 1 - VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_MEDIUM_NV = 2 - VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_FAST_NV = 3 - VkOpticalFlowSessionBindingPointNV* {.size: sizeof(cint).} = enum - VK_OPTICAL_FLOW_SESSION_BINDING_POINT_UNKNOWN_NV = 0 - VK_OPTICAL_FLOW_SESSION_BINDING_POINT_INPUT_NV = 1 - VK_OPTICAL_FLOW_SESSION_BINDING_POINT_REFERENCE_NV = 2 - VK_OPTICAL_FLOW_SESSION_BINDING_POINT_HINT_NV = 3 - VK_OPTICAL_FLOW_SESSION_BINDING_POINT_FLOW_VECTOR_NV = 4 - VK_OPTICAL_FLOW_SESSION_BINDING_POINT_BACKWARD_FLOW_VECTOR_NV = 5 - VK_OPTICAL_FLOW_SESSION_BINDING_POINT_COST_NV = 6 - VK_OPTICAL_FLOW_SESSION_BINDING_POINT_BACKWARD_COST_NV = 7 - VK_OPTICAL_FLOW_SESSION_BINDING_POINT_GLOBAL_FLOW_NV = 8 - VkOpticalFlowSessionCreateFlagBitsNV* {.size: sizeof(cint).} = enum - VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_HINT_BIT_NV = 0b00000000000000000000000000000001 - VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_COST_BIT_NV = 0b00000000000000000000000000000010 - VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_GLOBAL_FLOW_BIT_NV = 0b00000000000000000000000000000100 - VK_OPTICAL_FLOW_SESSION_CREATE_ALLOW_REGIONS_BIT_NV = 0b00000000000000000000000000001000 - VK_OPTICAL_FLOW_SESSION_CREATE_BOTH_DIRECTIONS_BIT_NV = 0b00000000000000000000000000010000 -func toBits*(flags: openArray[VkOpticalFlowSessionCreateFlagBitsNV]): VkOpticalFlowSessionCreateFlagsNV = - for flag in flags: - result = VkOpticalFlowSessionCreateFlagsNV(uint(result) or uint(flag)) -func toEnums*(number: VkOpticalFlowSessionCreateFlagsNV): seq[VkOpticalFlowSessionCreateFlagBitsNV] = - for value in VkOpticalFlowSessionCreateFlagBitsNV.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkOpticalFlowSessionCreateFlagsNV): bool = cint(a) == cint(b) -type - VkOpticalFlowExecuteFlagBitsNV* {.size: sizeof(cint).} = enum - VK_OPTICAL_FLOW_EXECUTE_DISABLE_TEMPORAL_HINTS_BIT_NV = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkOpticalFlowExecuteFlagBitsNV]): VkOpticalFlowExecuteFlagsNV = - for flag in flags: - result = VkOpticalFlowExecuteFlagsNV(uint(result) or uint(flag)) -func toEnums*(number: VkOpticalFlowExecuteFlagsNV): seq[VkOpticalFlowExecuteFlagBitsNV] = - for value in VkOpticalFlowExecuteFlagBitsNV.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkOpticalFlowExecuteFlagsNV): bool = cint(a) == cint(b) -type - VkMicromapTypeEXT* {.size: sizeof(cint).} = enum - VK_MICROMAP_TYPE_OPACITY_MICROMAP_EXT = 0 - VkBuildMicromapFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_BUILD_MICROMAP_PREFER_FAST_TRACE_BIT_EXT = 0b00000000000000000000000000000001 - VK_BUILD_MICROMAP_PREFER_FAST_BUILD_BIT_EXT = 0b00000000000000000000000000000010 - VK_BUILD_MICROMAP_ALLOW_COMPACTION_BIT_EXT = 0b00000000000000000000000000000100 -func toBits*(flags: openArray[VkBuildMicromapFlagBitsEXT]): VkBuildMicromapFlagsEXT = - for flag in flags: - result = VkBuildMicromapFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkBuildMicromapFlagsEXT): seq[VkBuildMicromapFlagBitsEXT] = - for value in VkBuildMicromapFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkBuildMicromapFlagsEXT): bool = cint(a) == cint(b) -type - VkMicromapCreateFlagBitsEXT* {.size: sizeof(cint).} = enum - VK_MICROMAP_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT = 0b00000000000000000000000000000001 -func toBits*(flags: openArray[VkMicromapCreateFlagBitsEXT]): VkMicromapCreateFlagsEXT = - for flag in flags: - result = VkMicromapCreateFlagsEXT(uint(result) or uint(flag)) -func toEnums*(number: VkMicromapCreateFlagsEXT): seq[VkMicromapCreateFlagBitsEXT] = - for value in VkMicromapCreateFlagBitsEXT.items: - if (value.ord and cint(number)) > 0: - result.add value -proc `==`*(a, b: VkMicromapCreateFlagsEXT): bool = cint(a) == cint(b) -type - VkCopyMicromapModeEXT* {.size: sizeof(cint).} = enum - VK_COPY_MICROMAP_MODE_CLONE_EXT = 0 - VK_COPY_MICROMAP_MODE_SERIALIZE_EXT = 1 - VK_COPY_MICROMAP_MODE_DESERIALIZE_EXT = 2 - VK_COPY_MICROMAP_MODE_COMPACT_EXT = 3 - VkBuildMicromapModeEXT* {.size: sizeof(cint).} = enum - VK_BUILD_MICROMAP_MODE_BUILD_EXT = 0 - VkOpacityMicromapFormatEXT* {.size: sizeof(cint).} = enum - VK_OPACITY_MICROMAP_FORMAT_2_STATE_EXT = 1 - VK_OPACITY_MICROMAP_FORMAT_4_STATE_EXT = 2 - VkOpacityMicromapSpecialIndexEXT* {.size: sizeof(cint).} = enum - VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT = -4 - VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT = -3 - VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT = -2 - VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT = -1 - VkDeviceFaultAddressTypeEXT* {.size: sizeof(cint).} = enum - VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT = 0 - VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT = 1 - VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT = 2 - VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT = 3 - VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT = 4 - VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT = 5 - VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT = 6 - VkDeviceFaultVendorBinaryHeaderVersionEXT* {.size: sizeof(cint).} = enum - VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_EXT_ENUM = 1 -proc `$`*(bitset: VkFramebufferCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkRenderPassCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkSamplerCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkPipelineCacheCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkPipelineShaderStageCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkDescriptorSetLayoutCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkInstanceCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkDeviceQueueCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkBufferCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkBufferUsageFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkColorComponentFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkCommandPoolCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkCommandPoolResetFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkCommandBufferResetFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkCommandBufferUsageFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkCullModeFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkFenceCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkFormatFeatureFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkImageAspectFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkImageCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkImageUsageFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkImageViewCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkMemoryHeapFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkAccessFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkMemoryPropertyFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkPipelineCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkQueryControlFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkQueryPipelineStatisticFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkQueryResultFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkQueueFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkShaderStageFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkSparseMemoryBindFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkStencilFaceFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkPipelineStageFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkSparseImageFormatFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkSampleCountFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkAttachmentDescriptionFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkDescriptorPoolCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkDependencyFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkEventCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkPipelineLayoutCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkIndirectCommandsLayoutUsageFlagsNV): string = $toEnums(bitset) -proc `$`*(bitset: VkIndirectStateFlagsNV): string = $toEnums(bitset) -proc `$`*(bitset: VkPrivateDataSlotCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkSubpassDescriptionFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkResolveModeFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkDescriptorBindingFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkConditionalRenderingFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkGeometryFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkGeometryInstanceFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkBuildAccelerationStructureFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkAccelerationStructureCreateFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkDeviceDiagnosticsConfigFlagsNV): string = $toEnums(bitset) -proc `$`*(bitset: VkPipelineCreationFeedbackFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkPerformanceCounterDescriptionFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkSemaphoreWaitFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkToolPurposeFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkAccessFlags2): string = $toEnums(bitset) -proc `$`*(bitset: VkPipelineStageFlags2): string = $toEnums(bitset) -proc `$`*(bitset: VkImageConstraintsInfoFlagsFUCHSIA): string = $toEnums(bitset) -proc `$`*(bitset: VkFormatFeatureFlags2): string = $toEnums(bitset) -proc `$`*(bitset: VkRenderingFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkPipelineDepthStencilStateCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkPipelineColorBlendStateCreateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkImageCompressionFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkImageCompressionFixedRateFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkExportMetalObjectTypeFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkDeviceAddressBindingFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkBuildMicromapFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkMicromapCreateFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkMemoryDecompressionMethodFlagsNV): string = $toEnums(bitset) -proc `$`*(bitset: VkCompositeAlphaFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkDisplayPlaneAlphaFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkSurfaceTransformFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkDebugReportFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkExternalMemoryHandleTypeFlagsNV): string = $toEnums(bitset) -proc `$`*(bitset: VkExternalMemoryFeatureFlagsNV): string = $toEnums(bitset) -proc `$`*(bitset: VkExternalMemoryHandleTypeFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkExternalMemoryFeatureFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkExternalSemaphoreHandleTypeFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkExternalSemaphoreFeatureFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkSemaphoreImportFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkExternalFenceHandleTypeFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkExternalFenceFeatureFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkFenceImportFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkSurfaceCounterFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkPeerMemoryFeatureFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkMemoryAllocateFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkDeviceGroupPresentModeFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkSwapchainCreateFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkSubgroupFeatureFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkDebugUtilsMessageSeverityFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkDebugUtilsMessageTypeFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkSwapchainImageUsageFlagsANDROID): string = $toEnums(bitset) -proc `$`*(bitset: VkSubmitFlags): string = $toEnums(bitset) -proc `$`*(bitset: VkGraphicsPipelineLibraryFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkOpticalFlowGridSizeFlagsNV): string = $toEnums(bitset) -proc `$`*(bitset: VkOpticalFlowUsageFlagsNV): string = $toEnums(bitset) -proc `$`*(bitset: VkOpticalFlowSessionCreateFlagsNV): string = $toEnums(bitset) -proc `$`*(bitset: VkOpticalFlowExecuteFlagsNV): string = $toEnums(bitset) -proc `$`*(bitset: VkPresentScalingFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkPresentGravityFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoCodecOperationFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoChromaSubsamplingFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoComponentBitDepthFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoCapabilityFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoSessionCreateFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoCodingControlFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoDecodeUsageFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoDecodeCapabilityFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoDecodeH264PictureLayoutFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeUsageFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeContentFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeCapabilityFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeRateControlModeFlagsKHR): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeH264CapabilityFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeH264InputModeFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeH264OutputModeFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeH265CapabilityFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeH265InputModeFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeH265OutputModeFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeH265CtbSizeFlagsEXT): string = $toEnums(bitset) -proc `$`*(bitset: VkVideoEncodeH265TransformBlockSizeFlagsEXT): string = $toEnums(bitset) -type - VkGeometryFlagsNV* = VkGeometryFlagsKHR - VkGeometryInstanceFlagsNV* = VkGeometryInstanceFlagsKHR - VkBuildAccelerationStructureFlagsNV* = VkBuildAccelerationStructureFlagsKHR - VkPrivateDataSlotCreateFlagsEXT* = VkPrivateDataSlotCreateFlags - VkDescriptorUpdateTemplateCreateFlagsKHR* = VkDescriptorUpdateTemplateCreateFlags - VkPipelineCreationFeedbackFlagsEXT* = VkPipelineCreationFeedbackFlags - VkSemaphoreWaitFlagsKHR* = VkSemaphoreWaitFlags - VkAccessFlags2KHR* = VkAccessFlags2 - VkPipelineStageFlags2KHR* = VkPipelineStageFlags2 - VkFormatFeatureFlags2KHR* = VkFormatFeatureFlags2 - VkRenderingFlagsKHR* = VkRenderingFlags - VkPeerMemoryFeatureFlagsKHR* = VkPeerMemoryFeatureFlags - VkMemoryAllocateFlagsKHR* = VkMemoryAllocateFlags - VkCommandPoolTrimFlagsKHR* = VkCommandPoolTrimFlags - VkExternalMemoryHandleTypeFlagsKHR* = VkExternalMemoryHandleTypeFlags - VkExternalMemoryFeatureFlagsKHR* = VkExternalMemoryFeatureFlags - VkExternalSemaphoreHandleTypeFlagsKHR* = VkExternalSemaphoreHandleTypeFlags - VkExternalSemaphoreFeatureFlagsKHR* = VkExternalSemaphoreFeatureFlags - VkSemaphoreImportFlagsKHR* = VkSemaphoreImportFlags - VkExternalFenceHandleTypeFlagsKHR* = VkExternalFenceHandleTypeFlags - VkExternalFenceFeatureFlagsKHR* = VkExternalFenceFeatureFlags - VkFenceImportFlagsKHR* = VkFenceImportFlags - VkDescriptorBindingFlagsEXT* = VkDescriptorBindingFlags - VkResolveModeFlagsKHR* = VkResolveModeFlags - VkToolPurposeFlagsEXT* = VkToolPurposeFlags - VkSubmitFlagsKHR* = VkSubmitFlags - VkPrivateDataSlotCreateFlagBitsEXT* = VkPrivateDataSlotCreateFlagBits - VkDescriptorUpdateTemplateTypeKHR* = VkDescriptorUpdateTemplateType - VkPointClippingBehaviorKHR* = VkPointClippingBehavior - VkQueueGlobalPriorityEXT* = VkQueueGlobalPriorityKHR - VkResolveModeFlagBitsKHR* = VkResolveModeFlagBits - VkDescriptorBindingFlagBitsEXT* = VkDescriptorBindingFlagBits - VkSemaphoreTypeKHR* = VkSemaphoreType - VkGeometryFlagBitsNV* = VkGeometryFlagBitsKHR - VkGeometryInstanceFlagBitsNV* = VkGeometryInstanceFlagBitsKHR - VkBuildAccelerationStructureFlagBitsNV* = VkBuildAccelerationStructureFlagBitsKHR - VkCopyAccelerationStructureModeNV* = VkCopyAccelerationStructureModeKHR - VkAccelerationStructureTypeNV* = VkAccelerationStructureTypeKHR - VkGeometryTypeNV* = VkGeometryTypeKHR - VkRayTracingShaderGroupTypeNV* = VkRayTracingShaderGroupTypeKHR - VkPipelineCreationFeedbackFlagBitsEXT* = VkPipelineCreationFeedbackFlagBits - VkSemaphoreWaitFlagBitsKHR* = VkSemaphoreWaitFlagBits - VkToolPurposeFlagBitsEXT* = VkToolPurposeFlagBits - VkAccessFlagBits2KHR* = VkAccessFlagBits2 - VkPipelineStageFlagBits2KHR* = VkPipelineStageFlagBits2 - VkFormatFeatureFlagBits2KHR* = VkFormatFeatureFlagBits2 - VkRenderingFlagBitsKHR* = VkRenderingFlagBits - VkExternalMemoryHandleTypeFlagBitsKHR* = VkExternalMemoryHandleTypeFlagBits - VkExternalMemoryFeatureFlagBitsKHR* = VkExternalMemoryFeatureFlagBits - VkExternalSemaphoreHandleTypeFlagBitsKHR* = VkExternalSemaphoreHandleTypeFlagBits - VkExternalSemaphoreFeatureFlagBitsKHR* = VkExternalSemaphoreFeatureFlagBits - VkSemaphoreImportFlagBitsKHR* = VkSemaphoreImportFlagBits - VkExternalFenceHandleTypeFlagBitsKHR* = VkExternalFenceHandleTypeFlagBits - VkExternalFenceFeatureFlagBitsKHR* = VkExternalFenceFeatureFlagBits - VkFenceImportFlagBitsKHR* = VkFenceImportFlagBits - VkPeerMemoryFeatureFlagBitsKHR* = VkPeerMemoryFeatureFlagBits - VkMemoryAllocateFlagBitsKHR* = VkMemoryAllocateFlagBits - VkTessellationDomainOriginKHR* = VkTessellationDomainOrigin - VkSamplerYcbcrModelConversionKHR* = VkSamplerYcbcrModelConversion - VkSamplerYcbcrRangeKHR* = VkSamplerYcbcrRange - VkChromaLocationKHR* = VkChromaLocation - VkSamplerReductionModeEXT* = VkSamplerReductionMode - VkShaderFloatControlsIndependenceKHR* = VkShaderFloatControlsIndependence - VkSubmitFlagBitsKHR* = VkSubmitFlagBits - VkDriverIdKHR* = VkDriverId -type - PFN_vkInternalAllocationNotification* = proc(pUserData: pointer, size: csize_t, allocationType: VkInternalAllocationType, allocationScope: VkSystemAllocationScope): void {.cdecl.} - PFN_vkInternalFreeNotification* = proc(pUserData: pointer, size: csize_t, allocationType: VkInternalAllocationType, allocationScope: VkSystemAllocationScope): void {.cdecl.} - PFN_vkReallocationFunction* = proc(pUserData: pointer, pOriginal: pointer, size: csize_t, alignment: csize_t, allocationScope: VkSystemAllocationScope): pointer {.cdecl.} - PFN_vkAllocationFunction* = proc(pUserData: pointer, size: csize_t, alignment: csize_t, allocationScope: VkSystemAllocationScope): pointer {.cdecl.} - PFN_vkFreeFunction* = proc(pUserData: pointer, pMemory: pointer): void {.cdecl.} - PFN_vkVoidFunction* = proc(): void {.cdecl.} - PFN_vkDebugReportCallbackEXT* = proc(flags: VkDebugReportFlagsEXT, objectType: VkDebugReportObjectTypeEXT, theobject: uint64, location: csize_t, messageCode: int32, pLayerPrefix: cstring, pMessage: cstring, pUserData: pointer): VkBool32 {.cdecl.} - PFN_vkDebugUtilsMessengerCallbackEXT* = proc(messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, messageTypes: VkDebugUtilsMessageTypeFlagsEXT, pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT, pUserData: pointer): VkBool32 {.cdecl.} - PFN_vkFaultCallbackFunction* = proc(unrecordedFaults: VkBool32, faultCount: uint32, pFaults: ptr VkFaultData): void {.cdecl.} - PFN_vkDeviceMemoryReportCallbackEXT* = proc(pCallbackData: ptr VkDeviceMemoryReportCallbackDataEXT, pUserData: pointer): void {.cdecl.} - PFN_vkGetInstanceProcAddrLUNARG* = proc(instance: VkInstance, pName: cstring): PFN_vkVoidFunction {.cdecl.} - VkBaseOutStructure* = object - sType*: VkStructureType - pNext*: ptr VkBaseOutStructure - VkBaseInStructure* = object - sType*: VkStructureType - pNext*: ptr VkBaseInStructure - VkOffset2D* = object - x*: int32 - y*: int32 - VkOffset3D* = object - x*: int32 - y*: int32 - z*: int32 - VkExtent2D* = object - width*: uint32 - height*: uint32 - VkExtent3D* = object - width*: uint32 - height*: uint32 - depth*: uint32 - VkViewport* = object - x*: float32 - y*: float32 - width*: float32 - height*: float32 - minDepth*: float32 - maxDepth*: float32 - VkRect2D* = object - offset*: VkOffset2D - extent*: VkExtent2D - VkClearRect* = object - rect*: VkRect2D - baseArrayLayer*: uint32 - layerCount*: uint32 - VkComponentMapping* = object - r*: VkComponentSwizzle - g*: VkComponentSwizzle - b*: VkComponentSwizzle - a*: VkComponentSwizzle - VkPhysicalDeviceProperties* = object - apiVersion*: uint32 - driverVersion*: uint32 - vendorID*: uint32 - deviceID*: uint32 - deviceType*: VkPhysicalDeviceType - deviceName*: array[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, char] - pipelineCacheUUID*: array[VK_UUID_SIZE, uint8] - limits*: VkPhysicalDeviceLimits - sparseProperties*: VkPhysicalDeviceSparseProperties - VkExtensionProperties* = object - extensionName*: array[VK_MAX_EXTENSION_NAME_SIZE, char] - specVersion*: uint32 - VkLayerProperties* = object - layerName*: array[VK_MAX_EXTENSION_NAME_SIZE, char] - specVersion*: uint32 - implementationVersion*: uint32 - description*: array[VK_MAX_DESCRIPTION_SIZE, char] - VkApplicationInfo* = object - sType*: VkStructureType - pNext*: pointer - pApplicationName*: cstring - applicationVersion*: uint32 - pEngineName*: cstring - engineVersion*: uint32 - apiVersion*: uint32 - VkAllocationCallbacks* = object - pUserData*: pointer - pfnAllocation*: PFN_vkAllocationFunction - pfnReallocation*: PFN_vkReallocationFunction - pfnFree*: PFN_vkFreeFunction - pfnInternalAllocation*: PFN_vkInternalAllocationNotification - pfnInternalFree*: PFN_vkInternalFreeNotification - VkDeviceQueueCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDeviceQueueCreateFlags - queueFamilyIndex*: uint32 - queueCount*: uint32 - pQueuePriorities*: ptr float32 - VkDeviceCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDeviceCreateFlags - queueCreateInfoCount*: uint32 - pQueueCreateInfos*: ptr VkDeviceQueueCreateInfo - enabledLayerCount*: uint32 - ppEnabledLayerNames*: cstringArray - enabledExtensionCount*: uint32 - ppEnabledExtensionNames*: cstringArray - pEnabledFeatures*: ptr VkPhysicalDeviceFeatures - VkInstanceCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkInstanceCreateFlags - pApplicationInfo*: ptr VkApplicationInfo - enabledLayerCount*: uint32 - ppEnabledLayerNames*: cstringArray - enabledExtensionCount*: uint32 - ppEnabledExtensionNames*: cstringArray - VkQueueFamilyProperties* = object - queueFlags*: VkQueueFlags - queueCount*: uint32 - timestampValidBits*: uint32 - minImageTransferGranularity*: VkExtent3D - VkPhysicalDeviceMemoryProperties* = object - memoryTypeCount*: uint32 - memoryTypes*: array[VK_MAX_MEMORY_TYPES, VkMemoryType] - memoryHeapCount*: uint32 - memoryHeaps*: array[VK_MAX_MEMORY_HEAPS, VkMemoryHeap] - VkMemoryAllocateInfo* = object - sType*: VkStructureType - pNext*: pointer - allocationSize*: VkDeviceSize - memoryTypeIndex*: uint32 - VkMemoryRequirements* = object - size*: VkDeviceSize - alignment*: VkDeviceSize - memoryTypeBits*: uint32 - VkSparseImageFormatProperties* = object - aspectMask*: VkImageAspectFlags - imageGranularity*: VkExtent3D - flags*: VkSparseImageFormatFlags - VkSparseImageMemoryRequirements* = object - formatProperties*: VkSparseImageFormatProperties - imageMipTailFirstLod*: uint32 - imageMipTailSize*: VkDeviceSize - imageMipTailOffset*: VkDeviceSize - imageMipTailStride*: VkDeviceSize - VkMemoryType* = object - propertyFlags*: VkMemoryPropertyFlags - heapIndex*: uint32 - VkMemoryHeap* = object - size*: VkDeviceSize - flags*: VkMemoryHeapFlags - VkMappedMemoryRange* = object - sType*: VkStructureType - pNext*: pointer - memory*: VkDeviceMemory - offset*: VkDeviceSize - size*: VkDeviceSize - VkFormatProperties* = object - linearTilingFeatures*: VkFormatFeatureFlags - optimalTilingFeatures*: VkFormatFeatureFlags - bufferFeatures*: VkFormatFeatureFlags - VkImageFormatProperties* = object - maxExtent*: VkExtent3D - maxMipLevels*: uint32 - maxArrayLayers*: uint32 - sampleCounts*: VkSampleCountFlags - maxResourceSize*: VkDeviceSize - VkDescriptorBufferInfo* = object - buffer*: VkBuffer - offset*: VkDeviceSize - range*: VkDeviceSize - VkDescriptorImageInfo* = object - sampler*: VkSampler - imageView*: VkImageView - imageLayout*: VkImageLayout - VkWriteDescriptorSet* = object - sType*: VkStructureType - pNext*: pointer - dstSet*: VkDescriptorSet - dstBinding*: uint32 - dstArrayElement*: uint32 - descriptorCount*: uint32 - descriptorType*: VkDescriptorType - pImageInfo*: ptr VkDescriptorImageInfo - pBufferInfo*: ptr VkDescriptorBufferInfo - pTexelBufferView*: ptr VkBufferView - VkCopyDescriptorSet* = object - sType*: VkStructureType - pNext*: pointer - srcSet*: VkDescriptorSet - srcBinding*: uint32 - srcArrayElement*: uint32 - dstSet*: VkDescriptorSet - dstBinding*: uint32 - dstArrayElement*: uint32 - descriptorCount*: uint32 - VkBufferCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkBufferCreateFlags - size*: VkDeviceSize - usage*: VkBufferUsageFlags - sharingMode*: VkSharingMode - queueFamilyIndexCount*: uint32 - pQueueFamilyIndices*: ptr uint32 - VkBufferViewCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkBufferViewCreateFlags - buffer*: VkBuffer - format*: VkFormat - offset*: VkDeviceSize - range*: VkDeviceSize - VkImageSubresource* = object - aspectMask*: VkImageAspectFlags - mipLevel*: uint32 - arrayLayer*: uint32 - VkImageSubresourceLayers* = object - aspectMask*: VkImageAspectFlags - mipLevel*: uint32 - baseArrayLayer*: uint32 - layerCount*: uint32 - VkImageSubresourceRange* = object - aspectMask*: VkImageAspectFlags - baseMipLevel*: uint32 - levelCount*: uint32 - baseArrayLayer*: uint32 - layerCount*: uint32 - VkMemoryBarrier* = object - sType*: VkStructureType - pNext*: pointer - srcAccessMask*: VkAccessFlags - dstAccessMask*: VkAccessFlags - VkBufferMemoryBarrier* = object - sType*: VkStructureType - pNext*: pointer - srcAccessMask*: VkAccessFlags - dstAccessMask*: VkAccessFlags - srcQueueFamilyIndex*: uint32 - dstQueueFamilyIndex*: uint32 - buffer*: VkBuffer - offset*: VkDeviceSize - size*: VkDeviceSize - VkImageMemoryBarrier* = object - sType*: VkStructureType - pNext*: pointer - srcAccessMask*: VkAccessFlags - dstAccessMask*: VkAccessFlags - oldLayout*: VkImageLayout - newLayout*: VkImageLayout - srcQueueFamilyIndex*: uint32 - dstQueueFamilyIndex*: uint32 - image*: VkImage - subresourceRange*: VkImageSubresourceRange - VkImageCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkImageCreateFlags - imageType*: VkImageType - format*: VkFormat - extent*: VkExtent3D - mipLevels*: uint32 - arrayLayers*: uint32 - samples*: VkSampleCountFlagBits - tiling*: VkImageTiling - usage*: VkImageUsageFlags - sharingMode*: VkSharingMode - queueFamilyIndexCount*: uint32 - pQueueFamilyIndices*: ptr uint32 - initialLayout*: VkImageLayout - VkSubresourceLayout* = object - offset*: VkDeviceSize - size*: VkDeviceSize - rowPitch*: VkDeviceSize - arrayPitch*: VkDeviceSize - depthPitch*: VkDeviceSize - VkImageViewCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkImageViewCreateFlags - image*: VkImage - viewType*: VkImageViewType - format*: VkFormat - components*: VkComponentMapping - subresourceRange*: VkImageSubresourceRange - VkBufferCopy* = object - srcOffset*: VkDeviceSize - dstOffset*: VkDeviceSize - size*: VkDeviceSize - VkSparseMemoryBind* = object - resourceOffset*: VkDeviceSize - size*: VkDeviceSize - memory*: VkDeviceMemory - memoryOffset*: VkDeviceSize - flags*: VkSparseMemoryBindFlags - VkSparseImageMemoryBind* = object - subresource*: VkImageSubresource - offset*: VkOffset3D - extent*: VkExtent3D - memory*: VkDeviceMemory - memoryOffset*: VkDeviceSize - flags*: VkSparseMemoryBindFlags - VkSparseBufferMemoryBindInfo* = object - buffer*: VkBuffer - bindCount*: uint32 - pBinds*: ptr VkSparseMemoryBind - VkSparseImageOpaqueMemoryBindInfo* = object - image*: VkImage - bindCount*: uint32 - pBinds*: ptr VkSparseMemoryBind - VkSparseImageMemoryBindInfo* = object - image*: VkImage - bindCount*: uint32 - pBinds*: ptr VkSparseImageMemoryBind - VkBindSparseInfo* = object - sType*: VkStructureType - pNext*: pointer - waitSemaphoreCount*: uint32 - pWaitSemaphores*: ptr VkSemaphore - bufferBindCount*: uint32 - pBufferBinds*: ptr VkSparseBufferMemoryBindInfo - imageOpaqueBindCount*: uint32 - pImageOpaqueBinds*: ptr VkSparseImageOpaqueMemoryBindInfo - imageBindCount*: uint32 - pImageBinds*: ptr VkSparseImageMemoryBindInfo - signalSemaphoreCount*: uint32 - pSignalSemaphores*: ptr VkSemaphore - VkImageCopy* = object - srcSubresource*: VkImageSubresourceLayers - srcOffset*: VkOffset3D - dstSubresource*: VkImageSubresourceLayers - dstOffset*: VkOffset3D - extent*: VkExtent3D - VkImageBlit* = object - srcSubresource*: VkImageSubresourceLayers - srcOffsets*: array[2, VkOffset3D] - dstSubresource*: VkImageSubresourceLayers - dstOffsets*: array[2, VkOffset3D] - VkBufferImageCopy* = object - bufferOffset*: VkDeviceSize - bufferRowLength*: uint32 - bufferImageHeight*: uint32 - imageSubresource*: VkImageSubresourceLayers - imageOffset*: VkOffset3D - imageExtent*: VkExtent3D - VkCopyMemoryIndirectCommandNV* = object - srcAddress*: VkDeviceAddress - dstAddress*: VkDeviceAddress - size*: VkDeviceSize - VkCopyMemoryToImageIndirectCommandNV* = object - srcAddress*: VkDeviceAddress - bufferRowLength*: uint32 - bufferImageHeight*: uint32 - imageSubresource*: VkImageSubresourceLayers - imageOffset*: VkOffset3D - imageExtent*: VkExtent3D - VkImageResolve* = object - srcSubresource*: VkImageSubresourceLayers - srcOffset*: VkOffset3D - dstSubresource*: VkImageSubresourceLayers - dstOffset*: VkOffset3D - extent*: VkExtent3D - VkShaderModuleCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkShaderModuleCreateFlags - codeSize*: csize_t - pCode*: ptr uint32 - VkDescriptorSetLayoutBinding* = object - binding*: uint32 - descriptorType*: VkDescriptorType - descriptorCount*: uint32 - stageFlags*: VkShaderStageFlags - pImmutableSamplers*: ptr VkSampler - VkDescriptorSetLayoutCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDescriptorSetLayoutCreateFlags - bindingCount*: uint32 - pBindings*: ptr VkDescriptorSetLayoutBinding - VkDescriptorPoolSize* = object - thetype*: VkDescriptorType - descriptorCount*: uint32 - VkDescriptorPoolCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDescriptorPoolCreateFlags - maxSets*: uint32 - poolSizeCount*: uint32 - pPoolSizes*: ptr VkDescriptorPoolSize - VkDescriptorSetAllocateInfo* = object - sType*: VkStructureType - pNext*: pointer - descriptorPool*: VkDescriptorPool - descriptorSetCount*: uint32 - pSetLayouts*: ptr VkDescriptorSetLayout - VkSpecializationMapEntry* = object - constantID*: uint32 - offset*: uint32 - size*: csize_t - VkSpecializationInfo* = object - mapEntryCount*: uint32 - pMapEntries*: ptr VkSpecializationMapEntry - dataSize*: csize_t - pData*: pointer - VkPipelineShaderStageCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineShaderStageCreateFlags - stage*: VkShaderStageFlagBits - module*: VkShaderModule - pName*: cstring - pSpecializationInfo*: ptr VkSpecializationInfo - VkComputePipelineCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineCreateFlags - stage*: VkPipelineShaderStageCreateInfo - layout*: VkPipelineLayout - basePipelineHandle*: VkPipeline - basePipelineIndex*: int32 - VkVertexInputBindingDescription* = object - binding*: uint32 - stride*: uint32 - inputRate*: VkVertexInputRate - VkVertexInputAttributeDescription* = object - location*: uint32 - binding*: uint32 - format*: VkFormat - offset*: uint32 - VkPipelineVertexInputStateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineVertexInputStateCreateFlags - vertexBindingDescriptionCount*: uint32 - pVertexBindingDescriptions*: ptr VkVertexInputBindingDescription - vertexAttributeDescriptionCount*: uint32 - pVertexAttributeDescriptions*: ptr VkVertexInputAttributeDescription - VkPipelineInputAssemblyStateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineInputAssemblyStateCreateFlags - topology*: VkPrimitiveTopology - primitiveRestartEnable*: VkBool32 - VkPipelineTessellationStateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineTessellationStateCreateFlags - patchControlPoints*: uint32 - VkPipelineViewportStateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineViewportStateCreateFlags - viewportCount*: uint32 - pViewports*: ptr VkViewport - scissorCount*: uint32 - pScissors*: ptr VkRect2D - VkPipelineRasterizationStateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineRasterizationStateCreateFlags - depthClampEnable*: VkBool32 - rasterizerDiscardEnable*: VkBool32 - polygonMode*: VkPolygonMode - cullMode*: VkCullModeFlags - frontFace*: VkFrontFace - depthBiasEnable*: VkBool32 - depthBiasConstantFactor*: float32 - depthBiasClamp*: float32 - depthBiasSlopeFactor*: float32 - lineWidth*: float32 - VkPipelineMultisampleStateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineMultisampleStateCreateFlags - rasterizationSamples*: VkSampleCountFlagBits - sampleShadingEnable*: VkBool32 - minSampleShading*: float32 - pSampleMask*: ptr VkSampleMask - alphaToCoverageEnable*: VkBool32 - alphaToOneEnable*: VkBool32 - VkPipelineColorBlendAttachmentState* = object - blendEnable*: VkBool32 - srcColorBlendFactor*: VkBlendFactor - dstColorBlendFactor*: VkBlendFactor - colorBlendOp*: VkBlendOp - srcAlphaBlendFactor*: VkBlendFactor - dstAlphaBlendFactor*: VkBlendFactor - alphaBlendOp*: VkBlendOp - colorWriteMask*: VkColorComponentFlags - VkPipelineColorBlendStateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineColorBlendStateCreateFlags - logicOpEnable*: VkBool32 - logicOp*: VkLogicOp - attachmentCount*: uint32 - pAttachments*: ptr VkPipelineColorBlendAttachmentState - blendConstants*: array[4, float32] - VkPipelineDynamicStateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineDynamicStateCreateFlags - dynamicStateCount*: uint32 - pDynamicStates*: ptr VkDynamicState - VkStencilOpState* = object - failOp*: VkStencilOp - passOp*: VkStencilOp - depthFailOp*: VkStencilOp - compareOp*: VkCompareOp - compareMask*: uint32 - writeMask*: uint32 - reference*: uint32 - VkPipelineDepthStencilStateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineDepthStencilStateCreateFlags - depthTestEnable*: VkBool32 - depthWriteEnable*: VkBool32 - depthCompareOp*: VkCompareOp - depthBoundsTestEnable*: VkBool32 - stencilTestEnable*: VkBool32 - front*: VkStencilOpState - back*: VkStencilOpState - minDepthBounds*: float32 - maxDepthBounds*: float32 - VkGraphicsPipelineCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineCreateFlags - stageCount*: uint32 - pStages*: ptr VkPipelineShaderStageCreateInfo - pVertexInputState*: ptr VkPipelineVertexInputStateCreateInfo - pInputAssemblyState*: ptr VkPipelineInputAssemblyStateCreateInfo - pTessellationState*: ptr VkPipelineTessellationStateCreateInfo - pViewportState*: ptr VkPipelineViewportStateCreateInfo - pRasterizationState*: ptr VkPipelineRasterizationStateCreateInfo - pMultisampleState*: ptr VkPipelineMultisampleStateCreateInfo - pDepthStencilState*: ptr VkPipelineDepthStencilStateCreateInfo - pColorBlendState*: ptr VkPipelineColorBlendStateCreateInfo - pDynamicState*: ptr VkPipelineDynamicStateCreateInfo - layout*: VkPipelineLayout - renderPass*: VkRenderPass - subpass*: uint32 - basePipelineHandle*: VkPipeline - basePipelineIndex*: int32 - VkPipelineCacheCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineCacheCreateFlags - initialDataSize*: csize_t - pInitialData*: pointer - VkPipelineCacheHeaderVersionOne* = object - headerSize*: uint32 - headerVersion*: VkPipelineCacheHeaderVersion - vendorID*: uint32 - deviceID*: uint32 - pipelineCacheUUID*: array[VK_UUID_SIZE, uint8] - VkPipelineCacheStageValidationIndexEntry* = object - codeSize*: uint64 - codeOffset*: uint64 - VkPipelineCacheSafetyCriticalIndexEntry* = object - pipelineIdentifier*: array[VK_UUID_SIZE, uint8] - pipelineMemorySize*: uint64 - jsonSize*: uint64 - jsonOffset*: uint64 - stageIndexCount*: uint32 - stageIndexStride*: uint32 - stageIndexOffset*: uint64 - VkPipelineCacheHeaderVersionSafetyCriticalOne* = object - headerVersionOne*: VkPipelineCacheHeaderVersionOne - validationVersion*: VkPipelineCacheValidationVersion - implementationData*: uint32 - pipelineIndexCount*: uint32 - pipelineIndexStride*: uint32 - pipelineIndexOffset*: uint64 - VkPushConstantRange* = object - stageFlags*: VkShaderStageFlags - offset*: uint32 - size*: uint32 - VkPipelineLayoutCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineLayoutCreateFlags - setLayoutCount*: uint32 - pSetLayouts*: ptr VkDescriptorSetLayout - pushConstantRangeCount*: uint32 - pPushConstantRanges*: ptr VkPushConstantRange - VkSamplerCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkSamplerCreateFlags - magFilter*: VkFilter - minFilter*: VkFilter - mipmapMode*: VkSamplerMipmapMode - addressModeU*: VkSamplerAddressMode - addressModeV*: VkSamplerAddressMode - addressModeW*: VkSamplerAddressMode - mipLodBias*: float32 - anisotropyEnable*: VkBool32 - maxAnisotropy*: float32 - compareEnable*: VkBool32 - compareOp*: VkCompareOp - minLod*: float32 - maxLod*: float32 - borderColor*: VkBorderColor - unnormalizedCoordinates*: VkBool32 - VkCommandPoolCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkCommandPoolCreateFlags - queueFamilyIndex*: uint32 - VkCommandBufferAllocateInfo* = object - sType*: VkStructureType - pNext*: pointer - commandPool*: VkCommandPool - level*: VkCommandBufferLevel - commandBufferCount*: uint32 - VkCommandBufferInheritanceInfo* = object - sType*: VkStructureType - pNext*: pointer - renderPass*: VkRenderPass - subpass*: uint32 - framebuffer*: VkFramebuffer - occlusionQueryEnable*: VkBool32 - queryFlags*: VkQueryControlFlags - pipelineStatistics*: VkQueryPipelineStatisticFlags - VkCommandBufferBeginInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkCommandBufferUsageFlags - pInheritanceInfo*: ptr VkCommandBufferInheritanceInfo - VkRenderPassBeginInfo* = object - sType*: VkStructureType - pNext*: pointer - renderPass*: VkRenderPass - framebuffer*: VkFramebuffer - renderArea*: VkRect2D - clearValueCount*: uint32 - pClearValues*: ptr VkClearValue - VkClearColorValue* {.union.} = object - float32*: array[4, float32] - int32*: array[4, int32] - uint32*: array[4, uint32] - VkClearDepthStencilValue* = object - depth*: float32 - stencil*: uint32 - VkClearValue* {.union.} = object - color*: VkClearColorValue - depthStencil*: VkClearDepthStencilValue - VkClearAttachment* = object - aspectMask*: VkImageAspectFlags - colorAttachment*: uint32 - clearValue*: VkClearValue - VkAttachmentDescription* = object - flags*: VkAttachmentDescriptionFlags - format*: VkFormat - samples*: VkSampleCountFlagBits - loadOp*: VkAttachmentLoadOp - storeOp*: VkAttachmentStoreOp - stencilLoadOp*: VkAttachmentLoadOp - stencilStoreOp*: VkAttachmentStoreOp - initialLayout*: VkImageLayout - finalLayout*: VkImageLayout - VkAttachmentReference* = object - attachment*: uint32 - layout*: VkImageLayout - VkSubpassDescription* = object - flags*: VkSubpassDescriptionFlags - pipelineBindPoint*: VkPipelineBindPoint - inputAttachmentCount*: uint32 - pInputAttachments*: ptr VkAttachmentReference - colorAttachmentCount*: uint32 - pColorAttachments*: ptr VkAttachmentReference - pResolveAttachments*: ptr VkAttachmentReference - pDepthStencilAttachment*: ptr VkAttachmentReference - preserveAttachmentCount*: uint32 - pPreserveAttachments*: ptr uint32 - VkSubpassDependency* = object - srcSubpass*: uint32 - dstSubpass*: uint32 - srcStageMask*: VkPipelineStageFlags - dstStageMask*: VkPipelineStageFlags - srcAccessMask*: VkAccessFlags - dstAccessMask*: VkAccessFlags - dependencyFlags*: VkDependencyFlags - VkRenderPassCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkRenderPassCreateFlags - attachmentCount*: uint32 - pAttachments*: ptr VkAttachmentDescription - subpassCount*: uint32 - pSubpasses*: ptr VkSubpassDescription - dependencyCount*: uint32 - pDependencies*: ptr VkSubpassDependency - VkEventCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkEventCreateFlags - VkFenceCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkFenceCreateFlags - VkPhysicalDeviceFeatures* = object - robustBufferAccess*: VkBool32 - fullDrawIndexUint32*: VkBool32 - imageCubeArray*: VkBool32 - independentBlend*: VkBool32 - geometryShader*: VkBool32 - tessellationShader*: VkBool32 - sampleRateShading*: VkBool32 - dualSrcBlend*: VkBool32 - logicOp*: VkBool32 - multiDrawIndirect*: VkBool32 - drawIndirectFirstInstance*: VkBool32 - depthClamp*: VkBool32 - depthBiasClamp*: VkBool32 - fillModeNonSolid*: VkBool32 - depthBounds*: VkBool32 - wideLines*: VkBool32 - largePoints*: VkBool32 - alphaToOne*: VkBool32 - multiViewport*: VkBool32 - samplerAnisotropy*: VkBool32 - textureCompressionETC2*: VkBool32 - textureCompressionASTC_LDR*: VkBool32 - textureCompressionBC*: VkBool32 - occlusionQueryPrecise*: VkBool32 - pipelineStatisticsQuery*: VkBool32 - vertexPipelineStoresAndAtomics*: VkBool32 - fragmentStoresAndAtomics*: VkBool32 - shaderTessellationAndGeometryPointSize*: VkBool32 - shaderImageGatherExtended*: VkBool32 - shaderStorageImageExtendedFormats*: VkBool32 - shaderStorageImageMultisample*: VkBool32 - shaderStorageImageReadWithoutFormat*: VkBool32 - shaderStorageImageWriteWithoutFormat*: VkBool32 - shaderUniformBufferArrayDynamicIndexing*: VkBool32 - shaderSampledImageArrayDynamicIndexing*: VkBool32 - shaderStorageBufferArrayDynamicIndexing*: VkBool32 - shaderStorageImageArrayDynamicIndexing*: VkBool32 - shaderClipDistance*: VkBool32 - shaderCullDistance*: VkBool32 - shaderFloat64*: VkBool32 - shaderInt64*: VkBool32 - shaderInt16*: VkBool32 - shaderResourceResidency*: VkBool32 - shaderResourceMinLod*: VkBool32 - sparseBinding*: VkBool32 - sparseResidencyBuffer*: VkBool32 - sparseResidencyImage2D*: VkBool32 - sparseResidencyImage3D*: VkBool32 - sparseResidency2Samples*: VkBool32 - sparseResidency4Samples*: VkBool32 - sparseResidency8Samples*: VkBool32 - sparseResidency16Samples*: VkBool32 - sparseResidencyAliased*: VkBool32 - variableMultisampleRate*: VkBool32 - inheritedQueries*: VkBool32 - VkPhysicalDeviceSparseProperties* = object - residencyStandard2DBlockShape*: VkBool32 - residencyStandard2DMultisampleBlockShape*: VkBool32 - residencyStandard3DBlockShape*: VkBool32 - residencyAlignedMipSize*: VkBool32 - residencyNonResidentStrict*: VkBool32 - VkPhysicalDeviceLimits* = object - maxImageDimension1D*: uint32 - maxImageDimension2D*: uint32 - maxImageDimension3D*: uint32 - maxImageDimensionCube*: uint32 - maxImageArrayLayers*: uint32 - maxTexelBufferElements*: uint32 - maxUniformBufferRange*: uint32 - maxStorageBufferRange*: uint32 - maxPushConstantsSize*: uint32 - maxMemoryAllocationCount*: uint32 - maxSamplerAllocationCount*: uint32 - bufferImageGranularity*: VkDeviceSize - sparseAddressSpaceSize*: VkDeviceSize - maxBoundDescriptorSets*: uint32 - maxPerStageDescriptorSamplers*: uint32 - maxPerStageDescriptorUniformBuffers*: uint32 - maxPerStageDescriptorStorageBuffers*: uint32 - maxPerStageDescriptorSampledImages*: uint32 - maxPerStageDescriptorStorageImages*: uint32 - maxPerStageDescriptorInputAttachments*: uint32 - maxPerStageResources*: uint32 - maxDescriptorSetSamplers*: uint32 - maxDescriptorSetUniformBuffers*: uint32 - maxDescriptorSetUniformBuffersDynamic*: uint32 - maxDescriptorSetStorageBuffers*: uint32 - maxDescriptorSetStorageBuffersDynamic*: uint32 - maxDescriptorSetSampledImages*: uint32 - maxDescriptorSetStorageImages*: uint32 - maxDescriptorSetInputAttachments*: uint32 - maxVertexInputAttributes*: uint32 - maxVertexInputBindings*: uint32 - maxVertexInputAttributeOffset*: uint32 - maxVertexInputBindingStride*: uint32 - maxVertexOutputComponents*: uint32 - maxTessellationGenerationLevel*: uint32 - maxTessellationPatchSize*: uint32 - maxTessellationControlPerVertexInputComponents*: uint32 - maxTessellationControlPerVertexOutputComponents*: uint32 - maxTessellationControlPerPatchOutputComponents*: uint32 - maxTessellationControlTotalOutputComponents*: uint32 - maxTessellationEvaluationInputComponents*: uint32 - maxTessellationEvaluationOutputComponents*: uint32 - maxGeometryShaderInvocations*: uint32 - maxGeometryInputComponents*: uint32 - maxGeometryOutputComponents*: uint32 - maxGeometryOutputVertices*: uint32 - maxGeometryTotalOutputComponents*: uint32 - maxFragmentInputComponents*: uint32 - maxFragmentOutputAttachments*: uint32 - maxFragmentDualSrcAttachments*: uint32 - maxFragmentCombinedOutputResources*: uint32 - maxComputeSharedMemorySize*: uint32 - maxComputeWorkGroupCount*: array[3, uint32] - maxComputeWorkGroupInvocations*: uint32 - maxComputeWorkGroupSize*: array[3, uint32] - subPixelPrecisionBits*: uint32 - subTexelPrecisionBits*: uint32 - mipmapPrecisionBits*: uint32 - maxDrawIndexedIndexValue*: uint32 - maxDrawIndirectCount*: uint32 - maxSamplerLodBias*: float32 - maxSamplerAnisotropy*: float32 - maxViewports*: uint32 - maxViewportDimensions*: array[2, uint32] - viewportBoundsRange*: array[2, float32] - viewportSubPixelBits*: uint32 - minMemoryMapAlignment*: csize_t - minTexelBufferOffsetAlignment*: VkDeviceSize - minUniformBufferOffsetAlignment*: VkDeviceSize - minStorageBufferOffsetAlignment*: VkDeviceSize - minTexelOffset*: int32 - maxTexelOffset*: uint32 - minTexelGatherOffset*: int32 - maxTexelGatherOffset*: uint32 - minInterpolationOffset*: float32 - maxInterpolationOffset*: float32 - subPixelInterpolationOffsetBits*: uint32 - maxFramebufferWidth*: uint32 - maxFramebufferHeight*: uint32 - maxFramebufferLayers*: uint32 - framebufferColorSampleCounts*: VkSampleCountFlags - framebufferDepthSampleCounts*: VkSampleCountFlags - framebufferStencilSampleCounts*: VkSampleCountFlags - framebufferNoAttachmentsSampleCounts*: VkSampleCountFlags - maxColorAttachments*: uint32 - sampledImageColorSampleCounts*: VkSampleCountFlags - sampledImageIntegerSampleCounts*: VkSampleCountFlags - sampledImageDepthSampleCounts*: VkSampleCountFlags - sampledImageStencilSampleCounts*: VkSampleCountFlags - storageImageSampleCounts*: VkSampleCountFlags - maxSampleMaskWords*: uint32 - timestampComputeAndGraphics*: VkBool32 - timestampPeriod*: float32 - maxClipDistances*: uint32 - maxCullDistances*: uint32 - maxCombinedClipAndCullDistances*: uint32 - discreteQueuePriorities*: uint32 - pointSizeRange*: array[2, float32] - lineWidthRange*: array[2, float32] - pointSizeGranularity*: float32 - lineWidthGranularity*: float32 - strictLines*: VkBool32 - standardSampleLocations*: VkBool32 - optimalBufferCopyOffsetAlignment*: VkDeviceSize - optimalBufferCopyRowPitchAlignment*: VkDeviceSize - nonCoherentAtomSize*: VkDeviceSize - VkSemaphoreCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkSemaphoreCreateFlags - VkQueryPoolCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkQueryPoolCreateFlags - queryType*: VkQueryType - queryCount*: uint32 - pipelineStatistics*: VkQueryPipelineStatisticFlags - VkFramebufferCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkFramebufferCreateFlags - renderPass*: VkRenderPass - attachmentCount*: uint32 - pAttachments*: ptr VkImageView - width*: uint32 - height*: uint32 - layers*: uint32 - VkDrawIndirectCommand* = object - vertexCount*: uint32 - instanceCount*: uint32 - firstVertex*: uint32 - firstInstance*: uint32 - VkDrawIndexedIndirectCommand* = object - indexCount*: uint32 - instanceCount*: uint32 - firstIndex*: uint32 - vertexOffset*: int32 - firstInstance*: uint32 - VkDispatchIndirectCommand* = object - x*: uint32 - y*: uint32 - z*: uint32 - VkMultiDrawInfoEXT* = object - firstVertex*: uint32 - vertexCount*: uint32 - VkMultiDrawIndexedInfoEXT* = object - firstIndex*: uint32 - indexCount*: uint32 - vertexOffset*: int32 - VkSubmitInfo* = object - sType*: VkStructureType - pNext*: pointer - waitSemaphoreCount*: uint32 - pWaitSemaphores*: ptr VkSemaphore - pWaitDstStageMask*: ptr VkPipelineStageFlags - commandBufferCount*: uint32 - pCommandBuffers*: ptr VkCommandBuffer - signalSemaphoreCount*: uint32 - pSignalSemaphores*: ptr VkSemaphore - VkDisplayPropertiesKHR* = object - display*: VkDisplayKHR - displayName*: cstring - physicalDimensions*: VkExtent2D - physicalResolution*: VkExtent2D - supportedTransforms*: VkSurfaceTransformFlagsKHR - planeReorderPossible*: VkBool32 - persistentContent*: VkBool32 - VkDisplayPlanePropertiesKHR* = object - currentDisplay*: VkDisplayKHR - currentStackIndex*: uint32 - VkDisplayModeParametersKHR* = object - visibleRegion*: VkExtent2D - refreshRate*: uint32 - VkDisplayModePropertiesKHR* = object - displayMode*: VkDisplayModeKHR - parameters*: VkDisplayModeParametersKHR - VkDisplayModeCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDisplayModeCreateFlagsKHR - parameters*: VkDisplayModeParametersKHR - VkDisplayPlaneCapabilitiesKHR* = object - supportedAlpha*: VkDisplayPlaneAlphaFlagsKHR - minSrcPosition*: VkOffset2D - maxSrcPosition*: VkOffset2D - minSrcExtent*: VkExtent2D - maxSrcExtent*: VkExtent2D - minDstPosition*: VkOffset2D - maxDstPosition*: VkOffset2D - minDstExtent*: VkExtent2D - maxDstExtent*: VkExtent2D - VkDisplaySurfaceCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDisplaySurfaceCreateFlagsKHR - displayMode*: VkDisplayModeKHR - planeIndex*: uint32 - planeStackIndex*: uint32 - transform*: VkSurfaceTransformFlagBitsKHR - globalAlpha*: float32 - alphaMode*: VkDisplayPlaneAlphaFlagBitsKHR - imageExtent*: VkExtent2D - VkDisplayPresentInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - srcRect*: VkRect2D - dstRect*: VkRect2D - persistent*: VkBool32 - VkSurfaceCapabilitiesKHR* = object - minImageCount*: uint32 - maxImageCount*: uint32 - currentExtent*: VkExtent2D - minImageExtent*: VkExtent2D - maxImageExtent*: VkExtent2D - maxImageArrayLayers*: uint32 - supportedTransforms*: VkSurfaceTransformFlagsKHR - currentTransform*: VkSurfaceTransformFlagBitsKHR - supportedCompositeAlpha*: VkCompositeAlphaFlagsKHR - supportedUsageFlags*: VkImageUsageFlags - VkSurfaceFormatKHR* = object - format*: VkFormat - colorSpace*: VkColorSpaceKHR - VkSwapchainCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkSwapchainCreateFlagsKHR - surface*: VkSurfaceKHR - minImageCount*: uint32 - imageFormat*: VkFormat - imageColorSpace*: VkColorSpaceKHR - imageExtent*: VkExtent2D - imageArrayLayers*: uint32 - imageUsage*: VkImageUsageFlags - imageSharingMode*: VkSharingMode - queueFamilyIndexCount*: uint32 - pQueueFamilyIndices*: ptr uint32 - preTransform*: VkSurfaceTransformFlagBitsKHR - compositeAlpha*: VkCompositeAlphaFlagBitsKHR - presentMode*: VkPresentModeKHR - clipped*: VkBool32 - oldSwapchain*: VkSwapchainKHR - VkPresentInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - waitSemaphoreCount*: uint32 - pWaitSemaphores*: ptr VkSemaphore - swapchainCount*: uint32 - pSwapchains*: ptr VkSwapchainKHR - pImageIndices*: ptr uint32 - pResults*: ptr VkResult - VkDebugReportCallbackCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDebugReportFlagsEXT - pfnCallback*: PFN_vkDebugReportCallbackEXT - pUserData*: pointer - VkValidationFlagsEXT* = object - sType*: VkStructureType - pNext*: pointer - disabledValidationCheckCount*: uint32 - pDisabledValidationChecks*: ptr VkValidationCheckEXT - VkValidationFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - enabledValidationFeatureCount*: uint32 - pEnabledValidationFeatures*: ptr VkValidationFeatureEnableEXT - disabledValidationFeatureCount*: uint32 - pDisabledValidationFeatures*: ptr VkValidationFeatureDisableEXT - VkApplicationParametersEXT* = object - sType*: VkStructureType - pNext*: pointer - vendorID*: uint32 - deviceID*: uint32 - key*: uint32 - value*: uint64 - VkPipelineRasterizationStateRasterizationOrderAMD* = object - sType*: VkStructureType - pNext*: pointer - rasterizationOrder*: VkRasterizationOrderAMD - VkDebugMarkerObjectNameInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - objectType*: VkDebugReportObjectTypeEXT - theobject*: uint64 - pObjectName*: cstring - VkDebugMarkerObjectTagInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - objectType*: VkDebugReportObjectTypeEXT - theobject*: uint64 - tagName*: uint64 - tagSize*: csize_t - pTag*: pointer - VkDebugMarkerMarkerInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - pMarkerName*: cstring - color*: array[4, float32] - VkDedicatedAllocationImageCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - dedicatedAllocation*: VkBool32 - VkDedicatedAllocationBufferCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - dedicatedAllocation*: VkBool32 - VkDedicatedAllocationMemoryAllocateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - image*: VkImage - buffer*: VkBuffer - VkExternalImageFormatPropertiesNV* = object - imageFormatProperties*: VkImageFormatProperties - externalMemoryFeatures*: VkExternalMemoryFeatureFlagsNV - exportFromImportedHandleTypes*: VkExternalMemoryHandleTypeFlagsNV - compatibleHandleTypes*: VkExternalMemoryHandleTypeFlagsNV - VkExternalMemoryImageCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - handleTypes*: VkExternalMemoryHandleTypeFlagsNV - VkExportMemoryAllocateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - handleTypes*: VkExternalMemoryHandleTypeFlagsNV - VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - deviceGeneratedCommands*: VkBool32 - VkDevicePrivateDataCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - privateDataSlotRequestCount*: uint32 - VkDevicePrivateDataCreateInfoEXT* = object - VkPrivateDataSlotCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPrivateDataSlotCreateFlags - VkPrivateDataSlotCreateInfoEXT* = object - VkPhysicalDevicePrivateDataFeatures* = object - sType*: VkStructureType - pNext*: pointer - privateData*: VkBool32 - VkPhysicalDevicePrivateDataFeaturesEXT* = object - VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - maxGraphicsShaderGroupCount*: uint32 - maxIndirectSequenceCount*: uint32 - maxIndirectCommandsTokenCount*: uint32 - maxIndirectCommandsStreamCount*: uint32 - maxIndirectCommandsTokenOffset*: uint32 - maxIndirectCommandsStreamStride*: uint32 - minSequencesCountBufferOffsetAlignment*: uint32 - minSequencesIndexBufferOffsetAlignment*: uint32 - minIndirectCommandsBufferOffsetAlignment*: uint32 - VkPhysicalDeviceMultiDrawPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - maxMultiDrawCount*: uint32 - VkGraphicsShaderGroupCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - stageCount*: uint32 - pStages*: ptr VkPipelineShaderStageCreateInfo - pVertexInputState*: ptr VkPipelineVertexInputStateCreateInfo - pTessellationState*: ptr VkPipelineTessellationStateCreateInfo - VkGraphicsPipelineShaderGroupsCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - groupCount*: uint32 - pGroups*: ptr VkGraphicsShaderGroupCreateInfoNV - pipelineCount*: uint32 - pPipelines*: ptr VkPipeline - VkBindShaderGroupIndirectCommandNV* = object - groupIndex*: uint32 - VkBindIndexBufferIndirectCommandNV* = object - bufferAddress*: VkDeviceAddress - size*: uint32 - indexType*: VkIndexType - VkBindVertexBufferIndirectCommandNV* = object - bufferAddress*: VkDeviceAddress - size*: uint32 - stride*: uint32 - VkSetStateFlagsIndirectCommandNV* = object - data*: uint32 - VkIndirectCommandsStreamNV* = object - buffer*: VkBuffer - offset*: VkDeviceSize - VkIndirectCommandsLayoutTokenNV* = object - sType*: VkStructureType - pNext*: pointer - tokenType*: VkIndirectCommandsTokenTypeNV - stream*: uint32 - offset*: uint32 - vertexBindingUnit*: uint32 - vertexDynamicStride*: VkBool32 - pushconstantPipelineLayout*: VkPipelineLayout - pushconstantShaderStageFlags*: VkShaderStageFlags - pushconstantOffset*: uint32 - pushconstantSize*: uint32 - indirectStateFlags*: VkIndirectStateFlagsNV - indexTypeCount*: uint32 - pIndexTypes*: ptr VkIndexType - pIndexTypeValues*: ptr uint32 - VkIndirectCommandsLayoutCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkIndirectCommandsLayoutUsageFlagsNV - pipelineBindPoint*: VkPipelineBindPoint - tokenCount*: uint32 - pTokens*: ptr VkIndirectCommandsLayoutTokenNV - streamCount*: uint32 - pStreamStrides*: ptr uint32 - VkGeneratedCommandsInfoNV* = object - sType*: VkStructureType - pNext*: pointer - pipelineBindPoint*: VkPipelineBindPoint - pipeline*: VkPipeline - indirectCommandsLayout*: VkIndirectCommandsLayoutNV - streamCount*: uint32 - pStreams*: ptr VkIndirectCommandsStreamNV - sequencesCount*: uint32 - preprocessBuffer*: VkBuffer - preprocessOffset*: VkDeviceSize - preprocessSize*: VkDeviceSize - sequencesCountBuffer*: VkBuffer - sequencesCountOffset*: VkDeviceSize - sequencesIndexBuffer*: VkBuffer - sequencesIndexOffset*: VkDeviceSize - VkGeneratedCommandsMemoryRequirementsInfoNV* = object - sType*: VkStructureType - pNext*: pointer - pipelineBindPoint*: VkPipelineBindPoint - pipeline*: VkPipeline - indirectCommandsLayout*: VkIndirectCommandsLayoutNV - maxSequencesCount*: uint32 - VkPhysicalDeviceFeatures2* = object - sType*: VkStructureType - pNext*: pointer - features*: VkPhysicalDeviceFeatures - VkPhysicalDeviceFeatures2KHR* = object - VkPhysicalDeviceProperties2* = object - sType*: VkStructureType - pNext*: pointer - properties*: VkPhysicalDeviceProperties - VkPhysicalDeviceProperties2KHR* = object - VkFormatProperties2* = object - sType*: VkStructureType - pNext*: pointer - formatProperties*: VkFormatProperties - VkFormatProperties2KHR* = object - VkImageFormatProperties2* = object - sType*: VkStructureType - pNext*: pointer - imageFormatProperties*: VkImageFormatProperties - VkImageFormatProperties2KHR* = object - VkPhysicalDeviceImageFormatInfo2* = object - sType*: VkStructureType - pNext*: pointer - format*: VkFormat - thetype*: VkImageType - tiling*: VkImageTiling - usage*: VkImageUsageFlags - flags*: VkImageCreateFlags - VkPhysicalDeviceImageFormatInfo2KHR* = object - VkQueueFamilyProperties2* = object - sType*: VkStructureType - pNext*: pointer - queueFamilyProperties*: VkQueueFamilyProperties - VkQueueFamilyProperties2KHR* = object - VkPhysicalDeviceMemoryProperties2* = object - sType*: VkStructureType - pNext*: pointer - memoryProperties*: VkPhysicalDeviceMemoryProperties - VkPhysicalDeviceMemoryProperties2KHR* = object - VkSparseImageFormatProperties2* = object - sType*: VkStructureType - pNext*: pointer - properties*: VkSparseImageFormatProperties - VkSparseImageFormatProperties2KHR* = object - VkPhysicalDeviceSparseImageFormatInfo2* = object - sType*: VkStructureType - pNext*: pointer - format*: VkFormat - thetype*: VkImageType - samples*: VkSampleCountFlagBits - usage*: VkImageUsageFlags - tiling*: VkImageTiling - VkPhysicalDeviceSparseImageFormatInfo2KHR* = object - VkPhysicalDevicePushDescriptorPropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - maxPushDescriptors*: uint32 - VkConformanceVersion* = object - major*: uint8 - minor*: uint8 - subminor*: uint8 - patch*: uint8 - VkConformanceVersionKHR* = object - VkPhysicalDeviceDriverProperties* = object - sType*: VkStructureType - pNext*: pointer - driverID*: VkDriverId - driverName*: array[VK_MAX_DRIVER_NAME_SIZE, char] - driverInfo*: array[VK_MAX_DRIVER_INFO_SIZE, char] - conformanceVersion*: VkConformanceVersion - VkPhysicalDeviceDriverPropertiesKHR* = object - VkPresentRegionsKHR* = object - sType*: VkStructureType - pNext*: pointer - swapchainCount*: uint32 - pRegions*: ptr VkPresentRegionKHR - VkPresentRegionKHR* = object - rectangleCount*: uint32 - pRectangles*: ptr VkRectLayerKHR - VkRectLayerKHR* = object - offset*: VkOffset2D - extent*: VkExtent2D - layer*: uint32 - VkPhysicalDeviceVariablePointersFeatures* = object - sType*: VkStructureType - pNext*: pointer - variablePointersStorageBuffer*: VkBool32 - variablePointers*: VkBool32 - VkPhysicalDeviceVariablePointersFeaturesKHR* = object - VkPhysicalDeviceVariablePointerFeaturesKHR* = object - VkPhysicalDeviceVariablePointerFeatures* = object - VkExternalMemoryProperties* = object - externalMemoryFeatures*: VkExternalMemoryFeatureFlags - exportFromImportedHandleTypes*: VkExternalMemoryHandleTypeFlags - compatibleHandleTypes*: VkExternalMemoryHandleTypeFlags - VkExternalMemoryPropertiesKHR* = object - VkPhysicalDeviceExternalImageFormatInfo* = object - sType*: VkStructureType - pNext*: pointer - handleType*: VkExternalMemoryHandleTypeFlagBits - VkPhysicalDeviceExternalImageFormatInfoKHR* = object - VkExternalImageFormatProperties* = object - sType*: VkStructureType - pNext*: pointer - externalMemoryProperties*: VkExternalMemoryProperties - VkExternalImageFormatPropertiesKHR* = object - VkPhysicalDeviceExternalBufferInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkBufferCreateFlags - usage*: VkBufferUsageFlags - handleType*: VkExternalMemoryHandleTypeFlagBits - VkPhysicalDeviceExternalBufferInfoKHR* = object - VkExternalBufferProperties* = object - sType*: VkStructureType - pNext*: pointer - externalMemoryProperties*: VkExternalMemoryProperties - VkExternalBufferPropertiesKHR* = object - VkPhysicalDeviceIDProperties* = object - sType*: VkStructureType - pNext*: pointer - deviceUUID*: array[VK_UUID_SIZE, uint8] - driverUUID*: array[VK_UUID_SIZE, uint8] - deviceLUID*: array[VK_LUID_SIZE, uint8] - deviceNodeMask*: uint32 - deviceLUIDValid*: VkBool32 - VkPhysicalDeviceIDPropertiesKHR* = object - VkExternalMemoryImageCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - handleTypes*: VkExternalMemoryHandleTypeFlags - VkExternalMemoryImageCreateInfoKHR* = object - VkExternalMemoryBufferCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - handleTypes*: VkExternalMemoryHandleTypeFlags - VkExternalMemoryBufferCreateInfoKHR* = object - VkExportMemoryAllocateInfo* = object - sType*: VkStructureType - pNext*: pointer - handleTypes*: VkExternalMemoryHandleTypeFlags - VkExportMemoryAllocateInfoKHR* = object - VkImportMemoryFdInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - handleType*: VkExternalMemoryHandleTypeFlagBits - fd*: cint - VkMemoryFdPropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - memoryTypeBits*: uint32 - VkMemoryGetFdInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - memory*: VkDeviceMemory - handleType*: VkExternalMemoryHandleTypeFlagBits - VkPhysicalDeviceExternalSemaphoreInfo* = object - sType*: VkStructureType - pNext*: pointer - handleType*: VkExternalSemaphoreHandleTypeFlagBits - VkPhysicalDeviceExternalSemaphoreInfoKHR* = object - VkExternalSemaphoreProperties* = object - sType*: VkStructureType - pNext*: pointer - exportFromImportedHandleTypes*: VkExternalSemaphoreHandleTypeFlags - compatibleHandleTypes*: VkExternalSemaphoreHandleTypeFlags - externalSemaphoreFeatures*: VkExternalSemaphoreFeatureFlags - VkExternalSemaphorePropertiesKHR* = object - VkExportSemaphoreCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - handleTypes*: VkExternalSemaphoreHandleTypeFlags - VkExportSemaphoreCreateInfoKHR* = object - VkImportSemaphoreFdInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - flags*: VkSemaphoreImportFlags - handleType*: VkExternalSemaphoreHandleTypeFlagBits - fd*: cint - VkSemaphoreGetFdInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - handleType*: VkExternalSemaphoreHandleTypeFlagBits - VkPhysicalDeviceExternalFenceInfo* = object - sType*: VkStructureType - pNext*: pointer - handleType*: VkExternalFenceHandleTypeFlagBits - VkPhysicalDeviceExternalFenceInfoKHR* = object - VkExternalFenceProperties* = object - sType*: VkStructureType - pNext*: pointer - exportFromImportedHandleTypes*: VkExternalFenceHandleTypeFlags - compatibleHandleTypes*: VkExternalFenceHandleTypeFlags - externalFenceFeatures*: VkExternalFenceFeatureFlags - VkExternalFencePropertiesKHR* = object - VkExportFenceCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - handleTypes*: VkExternalFenceHandleTypeFlags - VkExportFenceCreateInfoKHR* = object - VkImportFenceFdInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - fence*: VkFence - flags*: VkFenceImportFlags - handleType*: VkExternalFenceHandleTypeFlagBits - fd*: cint - VkFenceGetFdInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - fence*: VkFence - handleType*: VkExternalFenceHandleTypeFlagBits - VkPhysicalDeviceMultiviewFeatures* = object - sType*: VkStructureType - pNext*: pointer - multiview*: VkBool32 - multiviewGeometryShader*: VkBool32 - multiviewTessellationShader*: VkBool32 - VkPhysicalDeviceMultiviewFeaturesKHR* = object - VkPhysicalDeviceMultiviewProperties* = object - sType*: VkStructureType - pNext*: pointer - maxMultiviewViewCount*: uint32 - maxMultiviewInstanceIndex*: uint32 - VkPhysicalDeviceMultiviewPropertiesKHR* = object - VkRenderPassMultiviewCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - subpassCount*: uint32 - pViewMasks*: ptr uint32 - dependencyCount*: uint32 - pViewOffsets*: ptr int32 - correlationMaskCount*: uint32 - pCorrelationMasks*: ptr uint32 - VkRenderPassMultiviewCreateInfoKHR* = object - VkSurfaceCapabilities2EXT* = object - sType*: VkStructureType - pNext*: pointer - minImageCount*: uint32 - maxImageCount*: uint32 - currentExtent*: VkExtent2D - minImageExtent*: VkExtent2D - maxImageExtent*: VkExtent2D - maxImageArrayLayers*: uint32 - supportedTransforms*: VkSurfaceTransformFlagsKHR - currentTransform*: VkSurfaceTransformFlagBitsKHR - supportedCompositeAlpha*: VkCompositeAlphaFlagsKHR - supportedUsageFlags*: VkImageUsageFlags - supportedSurfaceCounters*: VkSurfaceCounterFlagsEXT - VkDisplayPowerInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - powerState*: VkDisplayPowerStateEXT - VkDeviceEventInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - deviceEvent*: VkDeviceEventTypeEXT - VkDisplayEventInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - displayEvent*: VkDisplayEventTypeEXT - VkSwapchainCounterCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - surfaceCounters*: VkSurfaceCounterFlagsEXT - VkPhysicalDeviceGroupProperties* = object - sType*: VkStructureType - pNext*: pointer - physicalDeviceCount*: uint32 - physicalDevices*: array[VK_MAX_DEVICE_GROUP_SIZE, VkPhysicalDevice] - subsetAllocation*: VkBool32 - VkPhysicalDeviceGroupPropertiesKHR* = object - VkMemoryAllocateFlagsInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkMemoryAllocateFlags - deviceMask*: uint32 - VkMemoryAllocateFlagsInfoKHR* = object - VkBindBufferMemoryInfo* = object - sType*: VkStructureType - pNext*: pointer - buffer*: VkBuffer - memory*: VkDeviceMemory - memoryOffset*: VkDeviceSize - VkBindBufferMemoryInfoKHR* = object - VkBindBufferMemoryDeviceGroupInfo* = object - sType*: VkStructureType - pNext*: pointer - deviceIndexCount*: uint32 - pDeviceIndices*: ptr uint32 - VkBindBufferMemoryDeviceGroupInfoKHR* = object - VkBindImageMemoryInfo* = object - sType*: VkStructureType - pNext*: pointer - image*: VkImage - memory*: VkDeviceMemory - memoryOffset*: VkDeviceSize - VkBindImageMemoryInfoKHR* = object - VkBindImageMemoryDeviceGroupInfo* = object - sType*: VkStructureType - pNext*: pointer - deviceIndexCount*: uint32 - pDeviceIndices*: ptr uint32 - splitInstanceBindRegionCount*: uint32 - pSplitInstanceBindRegions*: ptr VkRect2D - VkBindImageMemoryDeviceGroupInfoKHR* = object - VkDeviceGroupRenderPassBeginInfo* = object - sType*: VkStructureType - pNext*: pointer - deviceMask*: uint32 - deviceRenderAreaCount*: uint32 - pDeviceRenderAreas*: ptr VkRect2D - VkDeviceGroupRenderPassBeginInfoKHR* = object - VkDeviceGroupCommandBufferBeginInfo* = object - sType*: VkStructureType - pNext*: pointer - deviceMask*: uint32 - VkDeviceGroupCommandBufferBeginInfoKHR* = object - VkDeviceGroupSubmitInfo* = object - sType*: VkStructureType - pNext*: pointer - waitSemaphoreCount*: uint32 - pWaitSemaphoreDeviceIndices*: ptr uint32 - commandBufferCount*: uint32 - pCommandBufferDeviceMasks*: ptr uint32 - signalSemaphoreCount*: uint32 - pSignalSemaphoreDeviceIndices*: ptr uint32 - VkDeviceGroupSubmitInfoKHR* = object - VkDeviceGroupBindSparseInfo* = object - sType*: VkStructureType - pNext*: pointer - resourceDeviceIndex*: uint32 - memoryDeviceIndex*: uint32 - VkDeviceGroupBindSparseInfoKHR* = object - VkDeviceGroupPresentCapabilitiesKHR* = object - sType*: VkStructureType - pNext*: pointer - presentMask*: array[VK_MAX_DEVICE_GROUP_SIZE, uint32] - modes*: VkDeviceGroupPresentModeFlagsKHR - VkImageSwapchainCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - swapchain*: VkSwapchainKHR - VkBindImageMemorySwapchainInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - swapchain*: VkSwapchainKHR - imageIndex*: uint32 - VkAcquireNextImageInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - swapchain*: VkSwapchainKHR - timeout*: uint64 - semaphore*: VkSemaphore - fence*: VkFence - deviceMask*: uint32 - VkDeviceGroupPresentInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - swapchainCount*: uint32 - pDeviceMasks*: ptr uint32 - mode*: VkDeviceGroupPresentModeFlagBitsKHR - VkDeviceGroupDeviceCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - physicalDeviceCount*: uint32 - pPhysicalDevices*: ptr VkPhysicalDevice - VkDeviceGroupDeviceCreateInfoKHR* = object - VkDeviceGroupSwapchainCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - modes*: VkDeviceGroupPresentModeFlagsKHR - VkDescriptorUpdateTemplateEntry* = object - dstBinding*: uint32 - dstArrayElement*: uint32 - descriptorCount*: uint32 - descriptorType*: VkDescriptorType - offset*: csize_t - stride*: csize_t - VkDescriptorUpdateTemplateEntryKHR* = object - VkDescriptorUpdateTemplateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDescriptorUpdateTemplateCreateFlags - descriptorUpdateEntryCount*: uint32 - pDescriptorUpdateEntries*: ptr VkDescriptorUpdateTemplateEntry - templateType*: VkDescriptorUpdateTemplateType - descriptorSetLayout*: VkDescriptorSetLayout - pipelineBindPoint*: VkPipelineBindPoint - pipelineLayout*: VkPipelineLayout - set*: uint32 - VkDescriptorUpdateTemplateCreateInfoKHR* = object - VkXYColorEXT* = object - x*: float32 - y*: float32 - VkPhysicalDevicePresentIdFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - presentId*: VkBool32 - VkPresentIdKHR* = object - sType*: VkStructureType - pNext*: pointer - swapchainCount*: uint32 - pPresentIds*: ptr uint64 - VkPhysicalDevicePresentWaitFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - presentWait*: VkBool32 - VkHdrMetadataEXT* = object - sType*: VkStructureType - pNext*: pointer - displayPrimaryRed*: VkXYColorEXT - displayPrimaryGreen*: VkXYColorEXT - displayPrimaryBlue*: VkXYColorEXT - whitePoint*: VkXYColorEXT - maxLuminance*: float32 - minLuminance*: float32 - maxContentLightLevel*: float32 - maxFrameAverageLightLevel*: float32 - VkDisplayNativeHdrSurfaceCapabilitiesAMD* = object - sType*: VkStructureType - pNext*: pointer - localDimmingSupport*: VkBool32 - VkSwapchainDisplayNativeHdrCreateInfoAMD* = object - sType*: VkStructureType - pNext*: pointer - localDimmingEnable*: VkBool32 - VkRefreshCycleDurationGOOGLE* = object - refreshDuration*: uint64 - VkPastPresentationTimingGOOGLE* = object - presentID*: uint32 - desiredPresentTime*: uint64 - actualPresentTime*: uint64 - earliestPresentTime*: uint64 - presentMargin*: uint64 - VkPresentTimesInfoGOOGLE* = object - sType*: VkStructureType - pNext*: pointer - swapchainCount*: uint32 - pTimes*: ptr VkPresentTimeGOOGLE - VkPresentTimeGOOGLE* = object - presentID*: uint32 - desiredPresentTime*: uint64 - VkViewportWScalingNV* = object - xcoeff*: float32 - ycoeff*: float32 - VkPipelineViewportWScalingStateCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - viewportWScalingEnable*: VkBool32 - viewportCount*: uint32 - pViewportWScalings*: ptr VkViewportWScalingNV - VkViewportSwizzleNV* = object - x*: VkViewportCoordinateSwizzleNV - y*: VkViewportCoordinateSwizzleNV - z*: VkViewportCoordinateSwizzleNV - w*: VkViewportCoordinateSwizzleNV - VkPipelineViewportSwizzleStateCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineViewportSwizzleStateCreateFlagsNV - viewportCount*: uint32 - pViewportSwizzles*: ptr VkViewportSwizzleNV - VkPhysicalDeviceDiscardRectanglePropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - maxDiscardRectangles*: uint32 - VkPipelineDiscardRectangleStateCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineDiscardRectangleStateCreateFlagsEXT - discardRectangleMode*: VkDiscardRectangleModeEXT - discardRectangleCount*: uint32 - pDiscardRectangles*: ptr VkRect2D - VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX* = object - sType*: VkStructureType - pNext*: pointer - perViewPositionAllComponents*: VkBool32 - VkInputAttachmentAspectReference* = object - subpass*: uint32 - inputAttachmentIndex*: uint32 - aspectMask*: VkImageAspectFlags - VkInputAttachmentAspectReferenceKHR* = object - VkRenderPassInputAttachmentAspectCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - aspectReferenceCount*: uint32 - pAspectReferences*: ptr VkInputAttachmentAspectReference - VkRenderPassInputAttachmentAspectCreateInfoKHR* = object - VkPhysicalDeviceSurfaceInfo2KHR* = object - sType*: VkStructureType - pNext*: pointer - surface*: VkSurfaceKHR - VkSurfaceCapabilities2KHR* = object - sType*: VkStructureType - pNext*: pointer - surfaceCapabilities*: VkSurfaceCapabilitiesKHR - VkSurfaceFormat2KHR* = object - sType*: VkStructureType - pNext*: pointer - surfaceFormat*: VkSurfaceFormatKHR - VkDisplayProperties2KHR* = object - sType*: VkStructureType - pNext*: pointer - displayProperties*: VkDisplayPropertiesKHR - VkDisplayPlaneProperties2KHR* = object - sType*: VkStructureType - pNext*: pointer - displayPlaneProperties*: VkDisplayPlanePropertiesKHR - VkDisplayModeProperties2KHR* = object - sType*: VkStructureType - pNext*: pointer - displayModeProperties*: VkDisplayModePropertiesKHR - VkDisplayPlaneInfo2KHR* = object - sType*: VkStructureType - pNext*: pointer - mode*: VkDisplayModeKHR - planeIndex*: uint32 - VkDisplayPlaneCapabilities2KHR* = object - sType*: VkStructureType - pNext*: pointer - capabilities*: VkDisplayPlaneCapabilitiesKHR - VkSharedPresentSurfaceCapabilitiesKHR* = object - sType*: VkStructureType - pNext*: pointer - sharedPresentSupportedUsageFlags*: VkImageUsageFlags - VkPhysicalDevice16BitStorageFeatures* = object - sType*: VkStructureType - pNext*: pointer - storageBuffer16BitAccess*: VkBool32 - uniformAndStorageBuffer16BitAccess*: VkBool32 - storagePushConstant16*: VkBool32 - storageInputOutput16*: VkBool32 - VkPhysicalDevice16BitStorageFeaturesKHR* = object - VkPhysicalDeviceSubgroupProperties* = object - sType*: VkStructureType - pNext*: pointer - subgroupSize*: uint32 - supportedStages*: VkShaderStageFlags - supportedOperations*: VkSubgroupFeatureFlags - quadOperationsInAllStages*: VkBool32 - VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures* = object - sType*: VkStructureType - pNext*: pointer - shaderSubgroupExtendedTypes*: VkBool32 - VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR* = object - VkBufferMemoryRequirementsInfo2* = object - sType*: VkStructureType - pNext*: pointer - buffer*: VkBuffer - VkBufferMemoryRequirementsInfo2KHR* = object - VkDeviceBufferMemoryRequirements* = object - sType*: VkStructureType - pNext*: pointer - pCreateInfo*: ptr VkBufferCreateInfo - VkDeviceBufferMemoryRequirementsKHR* = object - VkImageMemoryRequirementsInfo2* = object - sType*: VkStructureType - pNext*: pointer - image*: VkImage - VkImageMemoryRequirementsInfo2KHR* = object - VkImageSparseMemoryRequirementsInfo2* = object - sType*: VkStructureType - pNext*: pointer - image*: VkImage - VkImageSparseMemoryRequirementsInfo2KHR* = object - VkDeviceImageMemoryRequirements* = object - sType*: VkStructureType - pNext*: pointer - pCreateInfo*: ptr VkImageCreateInfo - planeAspect*: VkImageAspectFlagBits - VkDeviceImageMemoryRequirementsKHR* = object - VkMemoryRequirements2* = object - sType*: VkStructureType - pNext*: pointer - memoryRequirements*: VkMemoryRequirements - VkMemoryRequirements2KHR* = object - VkSparseImageMemoryRequirements2* = object - sType*: VkStructureType - pNext*: pointer - memoryRequirements*: VkSparseImageMemoryRequirements - VkSparseImageMemoryRequirements2KHR* = object - VkPhysicalDevicePointClippingProperties* = object - sType*: VkStructureType - pNext*: pointer - pointClippingBehavior*: VkPointClippingBehavior - VkPhysicalDevicePointClippingPropertiesKHR* = object - VkMemoryDedicatedRequirements* = object - sType*: VkStructureType - pNext*: pointer - prefersDedicatedAllocation*: VkBool32 - requiresDedicatedAllocation*: VkBool32 - VkMemoryDedicatedRequirementsKHR* = object - VkMemoryDedicatedAllocateInfo* = object - sType*: VkStructureType - pNext*: pointer - image*: VkImage - buffer*: VkBuffer - VkMemoryDedicatedAllocateInfoKHR* = object - VkImageViewUsageCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - usage*: VkImageUsageFlags - VkImageViewSlicedCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - sliceOffset*: uint32 - sliceCount*: uint32 - VkImageViewUsageCreateInfoKHR* = object - VkPipelineTessellationDomainOriginStateCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - domainOrigin*: VkTessellationDomainOrigin - VkPipelineTessellationDomainOriginStateCreateInfoKHR* = object - VkSamplerYcbcrConversionInfo* = object - sType*: VkStructureType - pNext*: pointer - conversion*: VkSamplerYcbcrConversion - VkSamplerYcbcrConversionInfoKHR* = object - VkSamplerYcbcrConversionCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - format*: VkFormat - ycbcrModel*: VkSamplerYcbcrModelConversion - ycbcrRange*: VkSamplerYcbcrRange - components*: VkComponentMapping - xChromaOffset*: VkChromaLocation - yChromaOffset*: VkChromaLocation - chromaFilter*: VkFilter - forceExplicitReconstruction*: VkBool32 - VkSamplerYcbcrConversionCreateInfoKHR* = object - VkBindImagePlaneMemoryInfo* = object - sType*: VkStructureType - pNext*: pointer - planeAspect*: VkImageAspectFlagBits - VkBindImagePlaneMemoryInfoKHR* = object - VkImagePlaneMemoryRequirementsInfo* = object - sType*: VkStructureType - pNext*: pointer - planeAspect*: VkImageAspectFlagBits - VkImagePlaneMemoryRequirementsInfoKHR* = object - VkPhysicalDeviceSamplerYcbcrConversionFeatures* = object - sType*: VkStructureType - pNext*: pointer - samplerYcbcrConversion*: VkBool32 - VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR* = object - VkSamplerYcbcrConversionImageFormatProperties* = object - sType*: VkStructureType - pNext*: pointer - combinedImageSamplerDescriptorCount*: uint32 - VkSamplerYcbcrConversionImageFormatPropertiesKHR* = object - VkTextureLODGatherFormatPropertiesAMD* = object - sType*: VkStructureType - pNext*: pointer - supportsTextureGatherLODBiasAMD*: VkBool32 - VkConditionalRenderingBeginInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - buffer*: VkBuffer - offset*: VkDeviceSize - flags*: VkConditionalRenderingFlagsEXT - VkProtectedSubmitInfo* = object - sType*: VkStructureType - pNext*: pointer - protectedSubmit*: VkBool32 - VkPhysicalDeviceProtectedMemoryFeatures* = object - sType*: VkStructureType - pNext*: pointer - protectedMemory*: VkBool32 - VkPhysicalDeviceProtectedMemoryProperties* = object - sType*: VkStructureType - pNext*: pointer - protectedNoFault*: VkBool32 - VkDeviceQueueInfo2* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDeviceQueueCreateFlags - queueFamilyIndex*: uint32 - queueIndex*: uint32 - VkPipelineCoverageToColorStateCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineCoverageToColorStateCreateFlagsNV - coverageToColorEnable*: VkBool32 - coverageToColorLocation*: uint32 - VkPhysicalDeviceSamplerFilterMinmaxProperties* = object - sType*: VkStructureType - pNext*: pointer - filterMinmaxSingleComponentFormats*: VkBool32 - filterMinmaxImageComponentMapping*: VkBool32 - VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT* = object - VkSampleLocationEXT* = object - x*: float32 - y*: float32 - VkSampleLocationsInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - sampleLocationsPerPixel*: VkSampleCountFlagBits - sampleLocationGridSize*: VkExtent2D - sampleLocationsCount*: uint32 - pSampleLocations*: ptr VkSampleLocationEXT - VkAttachmentSampleLocationsEXT* = object - attachmentIndex*: uint32 - sampleLocationsInfo*: VkSampleLocationsInfoEXT - VkSubpassSampleLocationsEXT* = object - subpassIndex*: uint32 - sampleLocationsInfo*: VkSampleLocationsInfoEXT - VkRenderPassSampleLocationsBeginInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - attachmentInitialSampleLocationsCount*: uint32 - pAttachmentInitialSampleLocations*: ptr VkAttachmentSampleLocationsEXT - postSubpassSampleLocationsCount*: uint32 - pPostSubpassSampleLocations*: ptr VkSubpassSampleLocationsEXT - VkPipelineSampleLocationsStateCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - sampleLocationsEnable*: VkBool32 - sampleLocationsInfo*: VkSampleLocationsInfoEXT - VkPhysicalDeviceSampleLocationsPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - sampleLocationSampleCounts*: VkSampleCountFlags - maxSampleLocationGridSize*: VkExtent2D - sampleLocationCoordinateRange*: array[2, float32] - sampleLocationSubPixelBits*: uint32 - variableSampleLocations*: VkBool32 - VkMultisamplePropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - maxSampleLocationGridSize*: VkExtent2D - VkSamplerReductionModeCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - reductionMode*: VkSamplerReductionMode - VkSamplerReductionModeCreateInfoEXT* = object - VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - advancedBlendCoherentOperations*: VkBool32 - VkPhysicalDeviceMultiDrawFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - multiDraw*: VkBool32 - VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - advancedBlendMaxColorAttachments*: uint32 - advancedBlendIndependentBlend*: VkBool32 - advancedBlendNonPremultipliedSrcColor*: VkBool32 - advancedBlendNonPremultipliedDstColor*: VkBool32 - advancedBlendCorrelatedOverlap*: VkBool32 - advancedBlendAllOperations*: VkBool32 - VkPipelineColorBlendAdvancedStateCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - srcPremultiplied*: VkBool32 - dstPremultiplied*: VkBool32 - blendOverlap*: VkBlendOverlapEXT - VkPhysicalDeviceInlineUniformBlockFeatures* = object - sType*: VkStructureType - pNext*: pointer - inlineUniformBlock*: VkBool32 - descriptorBindingInlineUniformBlockUpdateAfterBind*: VkBool32 - VkPhysicalDeviceInlineUniformBlockFeaturesEXT* = object - VkPhysicalDeviceInlineUniformBlockProperties* = object - sType*: VkStructureType - pNext*: pointer - maxInlineUniformBlockSize*: uint32 - maxPerStageDescriptorInlineUniformBlocks*: uint32 - maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks*: uint32 - maxDescriptorSetInlineUniformBlocks*: uint32 - maxDescriptorSetUpdateAfterBindInlineUniformBlocks*: uint32 - VkPhysicalDeviceInlineUniformBlockPropertiesEXT* = object - VkWriteDescriptorSetInlineUniformBlock* = object - sType*: VkStructureType - pNext*: pointer - dataSize*: uint32 - pData*: pointer - VkWriteDescriptorSetInlineUniformBlockEXT* = object - VkDescriptorPoolInlineUniformBlockCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - maxInlineUniformBlockBindings*: uint32 - VkDescriptorPoolInlineUniformBlockCreateInfoEXT* = object - VkPipelineCoverageModulationStateCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineCoverageModulationStateCreateFlagsNV - coverageModulationMode*: VkCoverageModulationModeNV - coverageModulationTableEnable*: VkBool32 - coverageModulationTableCount*: uint32 - pCoverageModulationTable*: ptr float32 - VkImageFormatListCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - viewFormatCount*: uint32 - pViewFormats*: ptr VkFormat - VkImageFormatListCreateInfoKHR* = object - VkValidationCacheCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkValidationCacheCreateFlagsEXT - initialDataSize*: csize_t - pInitialData*: pointer - VkShaderModuleValidationCacheCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - validationCache*: VkValidationCacheEXT - VkPhysicalDeviceMaintenance3Properties* = object - sType*: VkStructureType - pNext*: pointer - maxPerSetDescriptors*: uint32 - maxMemoryAllocationSize*: VkDeviceSize - VkPhysicalDeviceMaintenance3PropertiesKHR* = object - VkPhysicalDeviceMaintenance4Features* = object - sType*: VkStructureType - pNext*: pointer - maintenance4*: VkBool32 - VkPhysicalDeviceMaintenance4FeaturesKHR* = object - VkPhysicalDeviceMaintenance4Properties* = object - sType*: VkStructureType - pNext*: pointer - maxBufferSize*: VkDeviceSize - VkPhysicalDeviceMaintenance4PropertiesKHR* = object - VkDescriptorSetLayoutSupport* = object - sType*: VkStructureType - pNext*: pointer - supported*: VkBool32 - VkDescriptorSetLayoutSupportKHR* = object - VkPhysicalDeviceShaderDrawParametersFeatures* = object - sType*: VkStructureType - pNext*: pointer - shaderDrawParameters*: VkBool32 - VkPhysicalDeviceShaderDrawParameterFeatures* = object - VkPhysicalDeviceShaderFloat16Int8Features* = object - sType*: VkStructureType - pNext*: pointer - shaderFloat16*: VkBool32 - shaderInt8*: VkBool32 - VkPhysicalDeviceShaderFloat16Int8FeaturesKHR* = object - VkPhysicalDeviceFloat16Int8FeaturesKHR* = object - VkPhysicalDeviceFloatControlsProperties* = object - sType*: VkStructureType - pNext*: pointer - denormBehaviorIndependence*: VkShaderFloatControlsIndependence - roundingModeIndependence*: VkShaderFloatControlsIndependence - shaderSignedZeroInfNanPreserveFloat16*: VkBool32 - shaderSignedZeroInfNanPreserveFloat32*: VkBool32 - shaderSignedZeroInfNanPreserveFloat64*: VkBool32 - shaderDenormPreserveFloat16*: VkBool32 - shaderDenormPreserveFloat32*: VkBool32 - shaderDenormPreserveFloat64*: VkBool32 - shaderDenormFlushToZeroFloat16*: VkBool32 - shaderDenormFlushToZeroFloat32*: VkBool32 - shaderDenormFlushToZeroFloat64*: VkBool32 - shaderRoundingModeRTEFloat16*: VkBool32 - shaderRoundingModeRTEFloat32*: VkBool32 - shaderRoundingModeRTEFloat64*: VkBool32 - shaderRoundingModeRTZFloat16*: VkBool32 - shaderRoundingModeRTZFloat32*: VkBool32 - shaderRoundingModeRTZFloat64*: VkBool32 - VkPhysicalDeviceFloatControlsPropertiesKHR* = object - VkPhysicalDeviceHostQueryResetFeatures* = object - sType*: VkStructureType - pNext*: pointer - hostQueryReset*: VkBool32 - VkPhysicalDeviceHostQueryResetFeaturesEXT* = object - VkShaderResourceUsageAMD* = object - numUsedVgprs*: uint32 - numUsedSgprs*: uint32 - ldsSizePerLocalWorkGroup*: uint32 - ldsUsageSizeInBytes*: csize_t - scratchMemUsageInBytes*: csize_t - VkShaderStatisticsInfoAMD* = object - shaderStageMask*: VkShaderStageFlags - resourceUsage*: VkShaderResourceUsageAMD - numPhysicalVgprs*: uint32 - numPhysicalSgprs*: uint32 - numAvailableVgprs*: uint32 - numAvailableSgprs*: uint32 - computeWorkGroupSize*: array[3, uint32] - VkDeviceQueueGlobalPriorityCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - globalPriority*: VkQueueGlobalPriorityKHR - VkDeviceQueueGlobalPriorityCreateInfoEXT* = object - VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - globalPriorityQuery*: VkBool32 - VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT* = object - VkQueueFamilyGlobalPriorityPropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - priorityCount*: uint32 - priorities*: array[VK_MAX_GLOBAL_PRIORITY_SIZE_KHR, VkQueueGlobalPriorityKHR] - VkQueueFamilyGlobalPriorityPropertiesEXT* = object - VkDebugUtilsObjectNameInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - objectType*: VkObjectType - objectHandle*: uint64 - pObjectName*: cstring - VkDebugUtilsObjectTagInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - objectType*: VkObjectType - objectHandle*: uint64 - tagName*: uint64 - tagSize*: csize_t - pTag*: pointer - VkDebugUtilsLabelEXT* = object - sType*: VkStructureType - pNext*: pointer - pLabelName*: cstring - color*: array[4, float32] - VkDebugUtilsMessengerCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDebugUtilsMessengerCreateFlagsEXT - messageSeverity*: VkDebugUtilsMessageSeverityFlagsEXT - messageType*: VkDebugUtilsMessageTypeFlagsEXT - pfnUserCallback*: PFN_vkDebugUtilsMessengerCallbackEXT - pUserData*: pointer - VkDebugUtilsMessengerCallbackDataEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDebugUtilsMessengerCallbackDataFlagsEXT - pMessageIdName*: cstring - messageIdNumber*: int32 - pMessage*: cstring - queueLabelCount*: uint32 - pQueueLabels*: ptr VkDebugUtilsLabelEXT - cmdBufLabelCount*: uint32 - pCmdBufLabels*: ptr VkDebugUtilsLabelEXT - objectCount*: uint32 - pObjects*: ptr VkDebugUtilsObjectNameInfoEXT - VkPhysicalDeviceDeviceMemoryReportFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - deviceMemoryReport*: VkBool32 - VkDeviceDeviceMemoryReportCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDeviceMemoryReportFlagsEXT - pfnUserCallback*: PFN_vkDeviceMemoryReportCallbackEXT - pUserData*: pointer - VkDeviceMemoryReportCallbackDataEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDeviceMemoryReportFlagsEXT - thetype*: VkDeviceMemoryReportEventTypeEXT - memoryObjectId*: uint64 - size*: VkDeviceSize - objectType*: VkObjectType - objectHandle*: uint64 - heapIndex*: uint32 - VkImportMemoryHostPointerInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - handleType*: VkExternalMemoryHandleTypeFlagBits - pHostPointer*: pointer - VkMemoryHostPointerPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - memoryTypeBits*: uint32 - VkPhysicalDeviceExternalMemoryHostPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - minImportedHostPointerAlignment*: VkDeviceSize - VkPhysicalDeviceConservativeRasterizationPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - primitiveOverestimationSize*: float32 - maxExtraPrimitiveOverestimationSize*: float32 - extraPrimitiveOverestimationSizeGranularity*: float32 - primitiveUnderestimation*: VkBool32 - conservativePointAndLineRasterization*: VkBool32 - degenerateTrianglesRasterized*: VkBool32 - degenerateLinesRasterized*: VkBool32 - fullyCoveredFragmentShaderInputVariable*: VkBool32 - conservativeRasterizationPostDepthCoverage*: VkBool32 - VkCalibratedTimestampInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - timeDomain*: VkTimeDomainEXT - VkPhysicalDeviceShaderCorePropertiesAMD* = object - sType*: VkStructureType - pNext*: pointer - shaderEngineCount*: uint32 - shaderArraysPerEngineCount*: uint32 - computeUnitsPerShaderArray*: uint32 - simdPerComputeUnit*: uint32 - wavefrontsPerSimd*: uint32 - wavefrontSize*: uint32 - sgprsPerSimd*: uint32 - minSgprAllocation*: uint32 - maxSgprAllocation*: uint32 - sgprAllocationGranularity*: uint32 - vgprsPerSimd*: uint32 - minVgprAllocation*: uint32 - maxVgprAllocation*: uint32 - vgprAllocationGranularity*: uint32 - VkPhysicalDeviceShaderCoreProperties2AMD* = object - sType*: VkStructureType - pNext*: pointer - shaderCoreFeatures*: VkShaderCorePropertiesFlagsAMD - activeComputeUnitCount*: uint32 - VkPipelineRasterizationConservativeStateCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineRasterizationConservativeStateCreateFlagsEXT - conservativeRasterizationMode*: VkConservativeRasterizationModeEXT - extraPrimitiveOverestimationSize*: float32 - VkPhysicalDeviceDescriptorIndexingFeatures* = object - sType*: VkStructureType - pNext*: pointer - shaderInputAttachmentArrayDynamicIndexing*: VkBool32 - shaderUniformTexelBufferArrayDynamicIndexing*: VkBool32 - shaderStorageTexelBufferArrayDynamicIndexing*: VkBool32 - shaderUniformBufferArrayNonUniformIndexing*: VkBool32 - shaderSampledImageArrayNonUniformIndexing*: VkBool32 - shaderStorageBufferArrayNonUniformIndexing*: VkBool32 - shaderStorageImageArrayNonUniformIndexing*: VkBool32 - shaderInputAttachmentArrayNonUniformIndexing*: VkBool32 - shaderUniformTexelBufferArrayNonUniformIndexing*: VkBool32 - shaderStorageTexelBufferArrayNonUniformIndexing*: VkBool32 - descriptorBindingUniformBufferUpdateAfterBind*: VkBool32 - descriptorBindingSampledImageUpdateAfterBind*: VkBool32 - descriptorBindingStorageImageUpdateAfterBind*: VkBool32 - descriptorBindingStorageBufferUpdateAfterBind*: VkBool32 - descriptorBindingUniformTexelBufferUpdateAfterBind*: VkBool32 - descriptorBindingStorageTexelBufferUpdateAfterBind*: VkBool32 - descriptorBindingUpdateUnusedWhilePending*: VkBool32 - descriptorBindingPartiallyBound*: VkBool32 - descriptorBindingVariableDescriptorCount*: VkBool32 - runtimeDescriptorArray*: VkBool32 - VkPhysicalDeviceDescriptorIndexingFeaturesEXT* = object - VkPhysicalDeviceDescriptorIndexingProperties* = object - sType*: VkStructureType - pNext*: pointer - maxUpdateAfterBindDescriptorsInAllPools*: uint32 - shaderUniformBufferArrayNonUniformIndexingNative*: VkBool32 - shaderSampledImageArrayNonUniformIndexingNative*: VkBool32 - shaderStorageBufferArrayNonUniformIndexingNative*: VkBool32 - shaderStorageImageArrayNonUniformIndexingNative*: VkBool32 - shaderInputAttachmentArrayNonUniformIndexingNative*: VkBool32 - robustBufferAccessUpdateAfterBind*: VkBool32 - quadDivergentImplicitLod*: VkBool32 - maxPerStageDescriptorUpdateAfterBindSamplers*: uint32 - maxPerStageDescriptorUpdateAfterBindUniformBuffers*: uint32 - maxPerStageDescriptorUpdateAfterBindStorageBuffers*: uint32 - maxPerStageDescriptorUpdateAfterBindSampledImages*: uint32 - maxPerStageDescriptorUpdateAfterBindStorageImages*: uint32 - maxPerStageDescriptorUpdateAfterBindInputAttachments*: uint32 - maxPerStageUpdateAfterBindResources*: uint32 - maxDescriptorSetUpdateAfterBindSamplers*: uint32 - maxDescriptorSetUpdateAfterBindUniformBuffers*: uint32 - maxDescriptorSetUpdateAfterBindUniformBuffersDynamic*: uint32 - maxDescriptorSetUpdateAfterBindStorageBuffers*: uint32 - maxDescriptorSetUpdateAfterBindStorageBuffersDynamic*: uint32 - maxDescriptorSetUpdateAfterBindSampledImages*: uint32 - maxDescriptorSetUpdateAfterBindStorageImages*: uint32 - maxDescriptorSetUpdateAfterBindInputAttachments*: uint32 - VkPhysicalDeviceDescriptorIndexingPropertiesEXT* = object - VkDescriptorSetLayoutBindingFlagsCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - bindingCount*: uint32 - pBindingFlags*: ptr VkDescriptorBindingFlags - VkDescriptorSetLayoutBindingFlagsCreateInfoEXT* = object - VkDescriptorSetVariableDescriptorCountAllocateInfo* = object - sType*: VkStructureType - pNext*: pointer - descriptorSetCount*: uint32 - pDescriptorCounts*: ptr uint32 - VkDescriptorSetVariableDescriptorCountAllocateInfoEXT* = object - VkDescriptorSetVariableDescriptorCountLayoutSupport* = object - sType*: VkStructureType - pNext*: pointer - maxVariableDescriptorCount*: uint32 - VkDescriptorSetVariableDescriptorCountLayoutSupportEXT* = object - VkAttachmentDescription2* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkAttachmentDescriptionFlags - format*: VkFormat - samples*: VkSampleCountFlagBits - loadOp*: VkAttachmentLoadOp - storeOp*: VkAttachmentStoreOp - stencilLoadOp*: VkAttachmentLoadOp - stencilStoreOp*: VkAttachmentStoreOp - initialLayout*: VkImageLayout - finalLayout*: VkImageLayout - VkAttachmentDescription2KHR* = object - VkAttachmentReference2* = object - sType*: VkStructureType - pNext*: pointer - attachment*: uint32 - layout*: VkImageLayout - aspectMask*: VkImageAspectFlags - VkAttachmentReference2KHR* = object - VkSubpassDescription2* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkSubpassDescriptionFlags - pipelineBindPoint*: VkPipelineBindPoint - viewMask*: uint32 - inputAttachmentCount*: uint32 - pInputAttachments*: ptr VkAttachmentReference2 - colorAttachmentCount*: uint32 - pColorAttachments*: ptr VkAttachmentReference2 - pResolveAttachments*: ptr VkAttachmentReference2 - pDepthStencilAttachment*: ptr VkAttachmentReference2 - preserveAttachmentCount*: uint32 - pPreserveAttachments*: ptr uint32 - VkSubpassDescription2KHR* = object - VkSubpassDependency2* = object - sType*: VkStructureType - pNext*: pointer - srcSubpass*: uint32 - dstSubpass*: uint32 - srcStageMask*: VkPipelineStageFlags - dstStageMask*: VkPipelineStageFlags - srcAccessMask*: VkAccessFlags - dstAccessMask*: VkAccessFlags - dependencyFlags*: VkDependencyFlags - viewOffset*: int32 - VkSubpassDependency2KHR* = object - VkRenderPassCreateInfo2* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkRenderPassCreateFlags - attachmentCount*: uint32 - pAttachments*: ptr VkAttachmentDescription2 - subpassCount*: uint32 - pSubpasses*: ptr VkSubpassDescription2 - dependencyCount*: uint32 - pDependencies*: ptr VkSubpassDependency2 - correlatedViewMaskCount*: uint32 - pCorrelatedViewMasks*: ptr uint32 - VkRenderPassCreateInfo2KHR* = object - VkSubpassBeginInfo* = object - sType*: VkStructureType - pNext*: pointer - contents*: VkSubpassContents - VkSubpassBeginInfoKHR* = object - VkSubpassEndInfo* = object - sType*: VkStructureType - pNext*: pointer - VkSubpassEndInfoKHR* = object - VkPhysicalDeviceTimelineSemaphoreFeatures* = object - sType*: VkStructureType - pNext*: pointer - timelineSemaphore*: VkBool32 - VkPhysicalDeviceTimelineSemaphoreFeaturesKHR* = object - VkPhysicalDeviceTimelineSemaphoreProperties* = object - sType*: VkStructureType - pNext*: pointer - maxTimelineSemaphoreValueDifference*: uint64 - VkPhysicalDeviceTimelineSemaphorePropertiesKHR* = object - VkSemaphoreTypeCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - semaphoreType*: VkSemaphoreType - initialValue*: uint64 - VkSemaphoreTypeCreateInfoKHR* = object - VkTimelineSemaphoreSubmitInfo* = object - sType*: VkStructureType - pNext*: pointer - waitSemaphoreValueCount*: uint32 - pWaitSemaphoreValues*: ptr uint64 - signalSemaphoreValueCount*: uint32 - pSignalSemaphoreValues*: ptr uint64 - VkTimelineSemaphoreSubmitInfoKHR* = object - VkSemaphoreWaitInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkSemaphoreWaitFlags - semaphoreCount*: uint32 - pSemaphores*: ptr VkSemaphore - pValues*: ptr uint64 - VkSemaphoreWaitInfoKHR* = object - VkSemaphoreSignalInfo* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - value*: uint64 - VkSemaphoreSignalInfoKHR* = object - VkVertexInputBindingDivisorDescriptionEXT* = object - binding*: uint32 - divisor*: uint32 - VkPipelineVertexInputDivisorStateCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - vertexBindingDivisorCount*: uint32 - pVertexBindingDivisors*: ptr VkVertexInputBindingDivisorDescriptionEXT - VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - maxVertexAttribDivisor*: uint32 - VkPhysicalDevicePCIBusInfoPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - pciDomain*: uint32 - pciBus*: uint32 - pciDevice*: uint32 - pciFunction*: uint32 - VkCommandBufferInheritanceConditionalRenderingInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - conditionalRenderingEnable*: VkBool32 - VkPhysicalDevice8BitStorageFeatures* = object - sType*: VkStructureType - pNext*: pointer - storageBuffer8BitAccess*: VkBool32 - uniformAndStorageBuffer8BitAccess*: VkBool32 - storagePushConstant8*: VkBool32 - VkPhysicalDevice8BitStorageFeaturesKHR* = object - VkPhysicalDeviceConditionalRenderingFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - conditionalRendering*: VkBool32 - inheritedConditionalRendering*: VkBool32 - VkPhysicalDeviceVulkanMemoryModelFeatures* = object - sType*: VkStructureType - pNext*: pointer - vulkanMemoryModel*: VkBool32 - vulkanMemoryModelDeviceScope*: VkBool32 - vulkanMemoryModelAvailabilityVisibilityChains*: VkBool32 - VkPhysicalDeviceVulkanMemoryModelFeaturesKHR* = object - VkPhysicalDeviceShaderAtomicInt64Features* = object - sType*: VkStructureType - pNext*: pointer - shaderBufferInt64Atomics*: VkBool32 - shaderSharedInt64Atomics*: VkBool32 - VkPhysicalDeviceShaderAtomicInt64FeaturesKHR* = object - VkPhysicalDeviceShaderAtomicFloatFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - shaderBufferFloat32Atomics*: VkBool32 - shaderBufferFloat32AtomicAdd*: VkBool32 - shaderBufferFloat64Atomics*: VkBool32 - shaderBufferFloat64AtomicAdd*: VkBool32 - shaderSharedFloat32Atomics*: VkBool32 - shaderSharedFloat32AtomicAdd*: VkBool32 - shaderSharedFloat64Atomics*: VkBool32 - shaderSharedFloat64AtomicAdd*: VkBool32 - shaderImageFloat32Atomics*: VkBool32 - shaderImageFloat32AtomicAdd*: VkBool32 - sparseImageFloat32Atomics*: VkBool32 - sparseImageFloat32AtomicAdd*: VkBool32 - VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - shaderBufferFloat16Atomics*: VkBool32 - shaderBufferFloat16AtomicAdd*: VkBool32 - shaderBufferFloat16AtomicMinMax*: VkBool32 - shaderBufferFloat32AtomicMinMax*: VkBool32 - shaderBufferFloat64AtomicMinMax*: VkBool32 - shaderSharedFloat16Atomics*: VkBool32 - shaderSharedFloat16AtomicAdd*: VkBool32 - shaderSharedFloat16AtomicMinMax*: VkBool32 - shaderSharedFloat32AtomicMinMax*: VkBool32 - shaderSharedFloat64AtomicMinMax*: VkBool32 - shaderImageFloat32AtomicMinMax*: VkBool32 - sparseImageFloat32AtomicMinMax*: VkBool32 - VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - vertexAttributeInstanceRateDivisor*: VkBool32 - vertexAttributeInstanceRateZeroDivisor*: VkBool32 - VkQueueFamilyCheckpointPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - checkpointExecutionStageMask*: VkPipelineStageFlags - VkCheckpointDataNV* = object - sType*: VkStructureType - pNext*: pointer - stage*: VkPipelineStageFlagBits - pCheckpointMarker*: pointer - VkPhysicalDeviceDepthStencilResolveProperties* = object - sType*: VkStructureType - pNext*: pointer - supportedDepthResolveModes*: VkResolveModeFlags - supportedStencilResolveModes*: VkResolveModeFlags - independentResolveNone*: VkBool32 - independentResolve*: VkBool32 - VkPhysicalDeviceDepthStencilResolvePropertiesKHR* = object - VkSubpassDescriptionDepthStencilResolve* = object - sType*: VkStructureType - pNext*: pointer - depthResolveMode*: VkResolveModeFlagBits - stencilResolveMode*: VkResolveModeFlagBits - pDepthStencilResolveAttachment*: ptr VkAttachmentReference2 - VkSubpassDescriptionDepthStencilResolveKHR* = object - VkImageViewASTCDecodeModeEXT* = object - sType*: VkStructureType - pNext*: pointer - decodeMode*: VkFormat - VkPhysicalDeviceASTCDecodeFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - decodeModeSharedExponent*: VkBool32 - VkPhysicalDeviceTransformFeedbackFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - transformFeedback*: VkBool32 - geometryStreams*: VkBool32 - VkPhysicalDeviceTransformFeedbackPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - maxTransformFeedbackStreams*: uint32 - maxTransformFeedbackBuffers*: uint32 - maxTransformFeedbackBufferSize*: VkDeviceSize - maxTransformFeedbackStreamDataSize*: uint32 - maxTransformFeedbackBufferDataSize*: uint32 - maxTransformFeedbackBufferDataStride*: uint32 - transformFeedbackQueries*: VkBool32 - transformFeedbackStreamsLinesTriangles*: VkBool32 - transformFeedbackRasterizationStreamSelect*: VkBool32 - transformFeedbackDraw*: VkBool32 - VkPipelineRasterizationStateStreamCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineRasterizationStateStreamCreateFlagsEXT - rasterizationStream*: uint32 - VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - representativeFragmentTest*: VkBool32 - VkPipelineRepresentativeFragmentTestStateCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - representativeFragmentTestEnable*: VkBool32 - VkPhysicalDeviceExclusiveScissorFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - exclusiveScissor*: VkBool32 - VkPipelineViewportExclusiveScissorStateCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - exclusiveScissorCount*: uint32 - pExclusiveScissors*: ptr VkRect2D - VkPhysicalDeviceCornerSampledImageFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - cornerSampledImage*: VkBool32 - VkPhysicalDeviceComputeShaderDerivativesFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - computeDerivativeGroupQuads*: VkBool32 - computeDerivativeGroupLinear*: VkBool32 - VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV* = object - VkPhysicalDeviceShaderImageFootprintFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - imageFootprint*: VkBool32 - VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - dedicatedAllocationImageAliasing*: VkBool32 - VkPhysicalDeviceCopyMemoryIndirectFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - indirectCopy*: VkBool32 - VkPhysicalDeviceCopyMemoryIndirectPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - supportedQueues*: VkQueueFlags - VkPhysicalDeviceMemoryDecompressionFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - memoryDecompression*: VkBool32 - VkPhysicalDeviceMemoryDecompressionPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - decompressionMethods*: VkMemoryDecompressionMethodFlagsNV - maxDecompressionIndirectCount*: uint64 - VkShadingRatePaletteNV* = object - shadingRatePaletteEntryCount*: uint32 - pShadingRatePaletteEntries*: ptr VkShadingRatePaletteEntryNV - VkPipelineViewportShadingRateImageStateCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - shadingRateImageEnable*: VkBool32 - viewportCount*: uint32 - pShadingRatePalettes*: ptr VkShadingRatePaletteNV - VkPhysicalDeviceShadingRateImageFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - shadingRateImage*: VkBool32 - shadingRateCoarseSampleOrder*: VkBool32 - VkPhysicalDeviceShadingRateImagePropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - shadingRateTexelSize*: VkExtent2D - shadingRatePaletteSize*: uint32 - shadingRateMaxCoarseSamples*: uint32 - VkPhysicalDeviceInvocationMaskFeaturesHUAWEI* = object - sType*: VkStructureType - pNext*: pointer - invocationMask*: VkBool32 - VkCoarseSampleLocationNV* = object - pixelX*: uint32 - pixelY*: uint32 - sample*: uint32 - VkCoarseSampleOrderCustomNV* = object - shadingRate*: VkShadingRatePaletteEntryNV - sampleCount*: uint32 - sampleLocationCount*: uint32 - pSampleLocations*: ptr VkCoarseSampleLocationNV - VkPipelineViewportCoarseSampleOrderStateCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - sampleOrderType*: VkCoarseSampleOrderTypeNV - customSampleOrderCount*: uint32 - pCustomSampleOrders*: ptr VkCoarseSampleOrderCustomNV - VkPhysicalDeviceMeshShaderFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - taskShader*: VkBool32 - meshShader*: VkBool32 - VkPhysicalDeviceMeshShaderPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - maxDrawMeshTasksCount*: uint32 - maxTaskWorkGroupInvocations*: uint32 - maxTaskWorkGroupSize*: array[3, uint32] - maxTaskTotalMemorySize*: uint32 - maxTaskOutputCount*: uint32 - maxMeshWorkGroupInvocations*: uint32 - maxMeshWorkGroupSize*: array[3, uint32] - maxMeshTotalMemorySize*: uint32 - maxMeshOutputVertices*: uint32 - maxMeshOutputPrimitives*: uint32 - maxMeshMultiviewViewCount*: uint32 - meshOutputPerVertexGranularity*: uint32 - meshOutputPerPrimitiveGranularity*: uint32 - VkDrawMeshTasksIndirectCommandNV* = object - taskCount*: uint32 - firstTask*: uint32 - VkPhysicalDeviceMeshShaderFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - taskShader*: VkBool32 - meshShader*: VkBool32 - multiviewMeshShader*: VkBool32 - primitiveFragmentShadingRateMeshShader*: VkBool32 - meshShaderQueries*: VkBool32 - VkPhysicalDeviceMeshShaderPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - maxTaskWorkGroupTotalCount*: uint32 - maxTaskWorkGroupCount*: array[3, uint32] - maxTaskWorkGroupInvocations*: uint32 - maxTaskWorkGroupSize*: array[3, uint32] - maxTaskPayloadSize*: uint32 - maxTaskSharedMemorySize*: uint32 - maxTaskPayloadAndSharedMemorySize*: uint32 - maxMeshWorkGroupTotalCount*: uint32 - maxMeshWorkGroupCount*: array[3, uint32] - maxMeshWorkGroupInvocations*: uint32 - maxMeshWorkGroupSize*: array[3, uint32] - maxMeshSharedMemorySize*: uint32 - maxMeshPayloadAndSharedMemorySize*: uint32 - maxMeshOutputMemorySize*: uint32 - maxMeshPayloadAndOutputMemorySize*: uint32 - maxMeshOutputComponents*: uint32 - maxMeshOutputVertices*: uint32 - maxMeshOutputPrimitives*: uint32 - maxMeshOutputLayers*: uint32 - maxMeshMultiviewViewCount*: uint32 - meshOutputPerVertexGranularity*: uint32 - meshOutputPerPrimitiveGranularity*: uint32 - maxPreferredTaskWorkGroupInvocations*: uint32 - maxPreferredMeshWorkGroupInvocations*: uint32 - prefersLocalInvocationVertexOutput*: VkBool32 - prefersLocalInvocationPrimitiveOutput*: VkBool32 - prefersCompactVertexOutput*: VkBool32 - prefersCompactPrimitiveOutput*: VkBool32 - VkDrawMeshTasksIndirectCommandEXT* = object - groupCountX*: uint32 - groupCountY*: uint32 - groupCountZ*: uint32 - VkRayTracingShaderGroupCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - thetype*: VkRayTracingShaderGroupTypeKHR - generalShader*: uint32 - closestHitShader*: uint32 - anyHitShader*: uint32 - intersectionShader*: uint32 - VkRayTracingShaderGroupCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - thetype*: VkRayTracingShaderGroupTypeKHR - generalShader*: uint32 - closestHitShader*: uint32 - anyHitShader*: uint32 - intersectionShader*: uint32 - pShaderGroupCaptureReplayHandle*: pointer - VkRayTracingPipelineCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineCreateFlags - stageCount*: uint32 - pStages*: ptr VkPipelineShaderStageCreateInfo - groupCount*: uint32 - pGroups*: ptr VkRayTracingShaderGroupCreateInfoNV - maxRecursionDepth*: uint32 - layout*: VkPipelineLayout - basePipelineHandle*: VkPipeline - basePipelineIndex*: int32 - VkRayTracingPipelineCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineCreateFlags - stageCount*: uint32 - pStages*: ptr VkPipelineShaderStageCreateInfo - groupCount*: uint32 - pGroups*: ptr VkRayTracingShaderGroupCreateInfoKHR - maxPipelineRayRecursionDepth*: uint32 - pLibraryInfo*: ptr VkPipelineLibraryCreateInfoKHR - pLibraryInterface*: ptr VkRayTracingPipelineInterfaceCreateInfoKHR - pDynamicState*: ptr VkPipelineDynamicStateCreateInfo - layout*: VkPipelineLayout - basePipelineHandle*: VkPipeline - basePipelineIndex*: int32 - VkGeometryTrianglesNV* = object - sType*: VkStructureType - pNext*: pointer - vertexData*: VkBuffer - vertexOffset*: VkDeviceSize - vertexCount*: uint32 - vertexStride*: VkDeviceSize - vertexFormat*: VkFormat - indexData*: VkBuffer - indexOffset*: VkDeviceSize - indexCount*: uint32 - indexType*: VkIndexType - transformData*: VkBuffer - transformOffset*: VkDeviceSize - VkGeometryAABBNV* = object - sType*: VkStructureType - pNext*: pointer - aabbData*: VkBuffer - numAABBs*: uint32 - stride*: uint32 - offset*: VkDeviceSize - VkGeometryDataNV* = object - triangles*: VkGeometryTrianglesNV - aabbs*: VkGeometryAABBNV - VkGeometryNV* = object - sType*: VkStructureType - pNext*: pointer - geometryType*: VkGeometryTypeKHR - geometry*: VkGeometryDataNV - flags*: VkGeometryFlagsKHR - VkAccelerationStructureInfoNV* = object - sType*: VkStructureType - pNext*: pointer - thetype*: VkAccelerationStructureTypeNV - flags*: VkBuildAccelerationStructureFlagsNV - instanceCount*: uint32 - geometryCount*: uint32 - pGeometries*: ptr VkGeometryNV - VkAccelerationStructureCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - compactedSize*: VkDeviceSize - info*: VkAccelerationStructureInfoNV - VkBindAccelerationStructureMemoryInfoNV* = object - sType*: VkStructureType - pNext*: pointer - accelerationStructure*: VkAccelerationStructureNV - memory*: VkDeviceMemory - memoryOffset*: VkDeviceSize - deviceIndexCount*: uint32 - pDeviceIndices*: ptr uint32 - VkWriteDescriptorSetAccelerationStructureKHR* = object - sType*: VkStructureType - pNext*: pointer - accelerationStructureCount*: uint32 - pAccelerationStructures*: ptr VkAccelerationStructureKHR - VkWriteDescriptorSetAccelerationStructureNV* = object - sType*: VkStructureType - pNext*: pointer - accelerationStructureCount*: uint32 - pAccelerationStructures*: ptr VkAccelerationStructureNV - VkAccelerationStructureMemoryRequirementsInfoNV* = object - sType*: VkStructureType - pNext*: pointer - thetype*: VkAccelerationStructureMemoryRequirementsTypeNV - accelerationStructure*: VkAccelerationStructureNV - VkPhysicalDeviceAccelerationStructureFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - accelerationStructure*: VkBool32 - accelerationStructureCaptureReplay*: VkBool32 - accelerationStructureIndirectBuild*: VkBool32 - accelerationStructureHostCommands*: VkBool32 - descriptorBindingAccelerationStructureUpdateAfterBind*: VkBool32 - VkPhysicalDeviceRayTracingPipelineFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - rayTracingPipeline*: VkBool32 - rayTracingPipelineShaderGroupHandleCaptureReplay*: VkBool32 - rayTracingPipelineShaderGroupHandleCaptureReplayMixed*: VkBool32 - rayTracingPipelineTraceRaysIndirect*: VkBool32 - rayTraversalPrimitiveCulling*: VkBool32 - VkPhysicalDeviceRayQueryFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - rayQuery*: VkBool32 - VkPhysicalDeviceAccelerationStructurePropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - maxGeometryCount*: uint64 - maxInstanceCount*: uint64 - maxPrimitiveCount*: uint64 - maxPerStageDescriptorAccelerationStructures*: uint32 - maxPerStageDescriptorUpdateAfterBindAccelerationStructures*: uint32 - maxDescriptorSetAccelerationStructures*: uint32 - maxDescriptorSetUpdateAfterBindAccelerationStructures*: uint32 - minAccelerationStructureScratchOffsetAlignment*: uint32 - VkPhysicalDeviceRayTracingPipelinePropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - shaderGroupHandleSize*: uint32 - maxRayRecursionDepth*: uint32 - maxShaderGroupStride*: uint32 - shaderGroupBaseAlignment*: uint32 - shaderGroupHandleCaptureReplaySize*: uint32 - maxRayDispatchInvocationCount*: uint32 - shaderGroupHandleAlignment*: uint32 - maxRayHitAttributeSize*: uint32 - VkPhysicalDeviceRayTracingPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - shaderGroupHandleSize*: uint32 - maxRecursionDepth*: uint32 - maxShaderGroupStride*: uint32 - shaderGroupBaseAlignment*: uint32 - maxGeometryCount*: uint64 - maxInstanceCount*: uint64 - maxTriangleCount*: uint64 - maxDescriptorSetAccelerationStructures*: uint32 - VkStridedDeviceAddressRegionKHR* = object - deviceAddress*: VkDeviceAddress - stride*: VkDeviceSize - size*: VkDeviceSize - VkTraceRaysIndirectCommandKHR* = object - width*: uint32 - height*: uint32 - depth*: uint32 - VkTraceRaysIndirectCommand2KHR* = object - raygenShaderRecordAddress*: VkDeviceAddress - raygenShaderRecordSize*: VkDeviceSize - missShaderBindingTableAddress*: VkDeviceAddress - missShaderBindingTableSize*: VkDeviceSize - missShaderBindingTableStride*: VkDeviceSize - hitShaderBindingTableAddress*: VkDeviceAddress - hitShaderBindingTableSize*: VkDeviceSize - hitShaderBindingTableStride*: VkDeviceSize - callableShaderBindingTableAddress*: VkDeviceAddress - callableShaderBindingTableSize*: VkDeviceSize - callableShaderBindingTableStride*: VkDeviceSize - width*: uint32 - height*: uint32 - depth*: uint32 - VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - rayTracingMaintenance1*: VkBool32 - rayTracingPipelineTraceRaysIndirect2*: VkBool32 - VkDrmFormatModifierPropertiesListEXT* = object - sType*: VkStructureType - pNext*: pointer - drmFormatModifierCount*: uint32 - pDrmFormatModifierProperties*: ptr VkDrmFormatModifierPropertiesEXT - VkDrmFormatModifierPropertiesEXT* = object - drmFormatModifier*: uint64 - drmFormatModifierPlaneCount*: uint32 - drmFormatModifierTilingFeatures*: VkFormatFeatureFlags - VkPhysicalDeviceImageDrmFormatModifierInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - drmFormatModifier*: uint64 - sharingMode*: VkSharingMode - queueFamilyIndexCount*: uint32 - pQueueFamilyIndices*: ptr uint32 - VkImageDrmFormatModifierListCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - drmFormatModifierCount*: uint32 - pDrmFormatModifiers*: ptr uint64 - VkImageDrmFormatModifierExplicitCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - drmFormatModifier*: uint64 - drmFormatModifierPlaneCount*: uint32 - pPlaneLayouts*: ptr VkSubresourceLayout - VkImageDrmFormatModifierPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - drmFormatModifier*: uint64 - VkImageStencilUsageCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - stencilUsage*: VkImageUsageFlags - VkImageStencilUsageCreateInfoEXT* = object - VkDeviceMemoryOverallocationCreateInfoAMD* = object - sType*: VkStructureType - pNext*: pointer - overallocationBehavior*: VkMemoryOverallocationBehaviorAMD - VkPhysicalDeviceFragmentDensityMapFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - fragmentDensityMap*: VkBool32 - fragmentDensityMapDynamic*: VkBool32 - fragmentDensityMapNonSubsampledImages*: VkBool32 - VkPhysicalDeviceFragmentDensityMap2FeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - fragmentDensityMapDeferred*: VkBool32 - VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM* = object - sType*: VkStructureType - pNext*: pointer - fragmentDensityMapOffset*: VkBool32 - VkPhysicalDeviceFragmentDensityMapPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - minFragmentDensityTexelSize*: VkExtent2D - maxFragmentDensityTexelSize*: VkExtent2D - fragmentDensityInvocations*: VkBool32 - VkPhysicalDeviceFragmentDensityMap2PropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - subsampledLoads*: VkBool32 - subsampledCoarseReconstructionEarlyAccess*: VkBool32 - maxSubsampledArrayLayers*: uint32 - maxDescriptorSetSubsampledSamplers*: uint32 - VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM* = object - sType*: VkStructureType - pNext*: pointer - fragmentDensityOffsetGranularity*: VkExtent2D - VkRenderPassFragmentDensityMapCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - fragmentDensityMapAttachment*: VkAttachmentReference - VkSubpassFragmentDensityMapOffsetEndInfoQCOM* = object - sType*: VkStructureType - pNext*: pointer - fragmentDensityOffsetCount*: uint32 - pFragmentDensityOffsets*: ptr VkOffset2D - VkPhysicalDeviceScalarBlockLayoutFeatures* = object - sType*: VkStructureType - pNext*: pointer - scalarBlockLayout*: VkBool32 - VkPhysicalDeviceScalarBlockLayoutFeaturesEXT* = object - VkSurfaceProtectedCapabilitiesKHR* = object - sType*: VkStructureType - pNext*: pointer - supportsProtected*: VkBool32 - VkPhysicalDeviceUniformBufferStandardLayoutFeatures* = object - sType*: VkStructureType - pNext*: pointer - uniformBufferStandardLayout*: VkBool32 - VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR* = object - VkPhysicalDeviceDepthClipEnableFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - depthClipEnable*: VkBool32 - VkPipelineRasterizationDepthClipStateCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineRasterizationDepthClipStateCreateFlagsEXT - depthClipEnable*: VkBool32 - VkPhysicalDeviceMemoryBudgetPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - heapBudget*: array[VK_MAX_MEMORY_HEAPS, VkDeviceSize] - heapUsage*: array[VK_MAX_MEMORY_HEAPS, VkDeviceSize] - VkPhysicalDeviceMemoryPriorityFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - memoryPriority*: VkBool32 - VkMemoryPriorityAllocateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - priority*: float32 - VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - pageableDeviceLocalMemory*: VkBool32 - VkPhysicalDeviceBufferDeviceAddressFeatures* = object - sType*: VkStructureType - pNext*: pointer - bufferDeviceAddress*: VkBool32 - bufferDeviceAddressCaptureReplay*: VkBool32 - bufferDeviceAddressMultiDevice*: VkBool32 - VkPhysicalDeviceBufferDeviceAddressFeaturesKHR* = object - VkPhysicalDeviceBufferDeviceAddressFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - bufferDeviceAddress*: VkBool32 - bufferDeviceAddressCaptureReplay*: VkBool32 - bufferDeviceAddressMultiDevice*: VkBool32 - VkPhysicalDeviceBufferAddressFeaturesEXT* = object - VkBufferDeviceAddressInfo* = object - sType*: VkStructureType - pNext*: pointer - buffer*: VkBuffer - VkBufferDeviceAddressInfoKHR* = object - VkBufferDeviceAddressInfoEXT* = object - VkBufferOpaqueCaptureAddressCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - opaqueCaptureAddress*: uint64 - VkBufferOpaqueCaptureAddressCreateInfoKHR* = object - VkBufferDeviceAddressCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - deviceAddress*: VkDeviceAddress - VkPhysicalDeviceImageViewImageFormatInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - imageViewType*: VkImageViewType - VkFilterCubicImageViewImageFormatPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - filterCubic*: VkBool32 - filterCubicMinmax*: VkBool32 - VkPhysicalDeviceImagelessFramebufferFeatures* = object - sType*: VkStructureType - pNext*: pointer - imagelessFramebuffer*: VkBool32 - VkPhysicalDeviceImagelessFramebufferFeaturesKHR* = object - VkFramebufferAttachmentsCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - attachmentImageInfoCount*: uint32 - pAttachmentImageInfos*: ptr VkFramebufferAttachmentImageInfo - VkFramebufferAttachmentsCreateInfoKHR* = object - VkFramebufferAttachmentImageInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkImageCreateFlags - usage*: VkImageUsageFlags - width*: uint32 - height*: uint32 - layerCount*: uint32 - viewFormatCount*: uint32 - pViewFormats*: ptr VkFormat - VkFramebufferAttachmentImageInfoKHR* = object - VkRenderPassAttachmentBeginInfo* = object - sType*: VkStructureType - pNext*: pointer - attachmentCount*: uint32 - pAttachments*: ptr VkImageView - VkRenderPassAttachmentBeginInfoKHR* = object - VkPhysicalDeviceTextureCompressionASTCHDRFeatures* = object - sType*: VkStructureType - pNext*: pointer - textureCompressionASTC_HDR*: VkBool32 - VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT* = object - VkPhysicalDeviceCooperativeMatrixFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - cooperativeMatrix*: VkBool32 - cooperativeMatrixRobustBufferAccess*: VkBool32 - VkPhysicalDeviceCooperativeMatrixPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - cooperativeMatrixSupportedStages*: VkShaderStageFlags - VkCooperativeMatrixPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - MSize*: uint32 - NSize*: uint32 - KSize*: uint32 - AType*: VkComponentTypeNV - BType*: VkComponentTypeNV - CType*: VkComponentTypeNV - DType*: VkComponentTypeNV - scope*: VkScopeNV - VkPhysicalDeviceYcbcrImageArraysFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - ycbcrImageArrays*: VkBool32 - VkImageViewHandleInfoNVX* = object - sType*: VkStructureType - pNext*: pointer - imageView*: VkImageView - descriptorType*: VkDescriptorType - sampler*: VkSampler - VkImageViewAddressPropertiesNVX* = object - sType*: VkStructureType - pNext*: pointer - deviceAddress*: VkDeviceAddress - size*: VkDeviceSize - VkPipelineCreationFeedback* = object - flags*: VkPipelineCreationFeedbackFlags - duration*: uint64 - VkPipelineCreationFeedbackEXT* = object - VkPipelineCreationFeedbackCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - pPipelineCreationFeedback*: ptr VkPipelineCreationFeedback - pipelineStageCreationFeedbackCount*: uint32 - pPipelineStageCreationFeedbacks*: ptr VkPipelineCreationFeedback - VkPipelineCreationFeedbackCreateInfoEXT* = object - VkPhysicalDevicePresentBarrierFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - presentBarrier*: VkBool32 - VkSurfaceCapabilitiesPresentBarrierNV* = object - sType*: VkStructureType - pNext*: pointer - presentBarrierSupported*: VkBool32 - VkSwapchainPresentBarrierCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - presentBarrierEnable*: VkBool32 - VkPhysicalDevicePerformanceQueryFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - performanceCounterQueryPools*: VkBool32 - performanceCounterMultipleQueryPools*: VkBool32 - VkPhysicalDevicePerformanceQueryPropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - allowCommandBufferQueryCopies*: VkBool32 - VkPerformanceCounterKHR* = object - sType*: VkStructureType - pNext*: pointer - unit*: VkPerformanceCounterUnitKHR - scope*: VkPerformanceCounterScopeKHR - storage*: VkPerformanceCounterStorageKHR - uuid*: array[VK_UUID_SIZE, uint8] - VkPerformanceCounterDescriptionKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPerformanceCounterDescriptionFlagsKHR - name*: array[VK_MAX_DESCRIPTION_SIZE, char] - category*: array[VK_MAX_DESCRIPTION_SIZE, char] - description*: array[VK_MAX_DESCRIPTION_SIZE, char] - VkQueryPoolPerformanceCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - queueFamilyIndex*: uint32 - counterIndexCount*: uint32 - pCounterIndices*: ptr uint32 - VkPerformanceCounterResultKHR* {.union.} = object - int32*: int32 - int64*: int64 - uint32*: uint32 - uint64*: uint64 - float32*: float32 - float64*: float64 - VkAcquireProfilingLockInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkAcquireProfilingLockFlagsKHR - timeout*: uint64 - VkPerformanceQuerySubmitInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - counterPassIndex*: uint32 - VkPerformanceQueryReservationInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - maxPerformanceQueriesPerPool*: uint32 - VkHeadlessSurfaceCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkHeadlessSurfaceCreateFlagsEXT - VkPhysicalDeviceCoverageReductionModeFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - coverageReductionMode*: VkBool32 - VkPipelineCoverageReductionStateCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkPipelineCoverageReductionStateCreateFlagsNV - coverageReductionMode*: VkCoverageReductionModeNV - VkFramebufferMixedSamplesCombinationNV* = object - sType*: VkStructureType - pNext*: pointer - coverageReductionMode*: VkCoverageReductionModeNV - rasterizationSamples*: VkSampleCountFlagBits - depthStencilSamples*: VkSampleCountFlags - colorSamples*: VkSampleCountFlags - VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL* = object - sType*: VkStructureType - pNext*: pointer - shaderIntegerFunctions2*: VkBool32 - VkPerformanceValueDataINTEL* {.union.} = object - value32*: uint32 - value64*: uint64 - valueFloat*: float32 - valueBool*: VkBool32 - valueString*: cstring - VkPerformanceValueINTEL* = object - thetype*: VkPerformanceValueTypeINTEL - data*: VkPerformanceValueDataINTEL - VkInitializePerformanceApiInfoINTEL* = object - sType*: VkStructureType - pNext*: pointer - pUserData*: pointer - VkQueryPoolPerformanceQueryCreateInfoINTEL* = object - sType*: VkStructureType - pNext*: pointer - performanceCountersSampling*: VkQueryPoolSamplingModeINTEL - VkQueryPoolCreateInfoINTEL* = object - VkPerformanceMarkerInfoINTEL* = object - sType*: VkStructureType - pNext*: pointer - marker*: uint64 - VkPerformanceStreamMarkerInfoINTEL* = object - sType*: VkStructureType - pNext*: pointer - marker*: uint32 - VkPerformanceOverrideInfoINTEL* = object - sType*: VkStructureType - pNext*: pointer - thetype*: VkPerformanceOverrideTypeINTEL - enable*: VkBool32 - parameter*: uint64 - VkPerformanceConfigurationAcquireInfoINTEL* = object - sType*: VkStructureType - pNext*: pointer - thetype*: VkPerformanceConfigurationTypeINTEL - VkPhysicalDeviceShaderClockFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - shaderSubgroupClock*: VkBool32 - shaderDeviceClock*: VkBool32 - VkPhysicalDeviceIndexTypeUint8FeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - indexTypeUint8*: VkBool32 - VkPhysicalDeviceShaderSMBuiltinsPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - shaderSMCount*: uint32 - shaderWarpsPerSM*: uint32 - VkPhysicalDeviceShaderSMBuiltinsFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - shaderSMBuiltins*: VkBool32 - VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - fragmentShaderSampleInterlock*: VkBool32 - fragmentShaderPixelInterlock*: VkBool32 - fragmentShaderShadingRateInterlock*: VkBool32 - VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures* = object - sType*: VkStructureType - pNext*: pointer - separateDepthStencilLayouts*: VkBool32 - VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR* = object - VkAttachmentReferenceStencilLayout* = object - sType*: VkStructureType - pNext*: pointer - stencilLayout*: VkImageLayout - VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - primitiveTopologyListRestart*: VkBool32 - primitiveTopologyPatchListRestart*: VkBool32 - VkAttachmentReferenceStencilLayoutKHR* = object - VkAttachmentDescriptionStencilLayout* = object - sType*: VkStructureType - pNext*: pointer - stencilInitialLayout*: VkImageLayout - stencilFinalLayout*: VkImageLayout - VkAttachmentDescriptionStencilLayoutKHR* = object - VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - pipelineExecutableInfo*: VkBool32 - VkPipelineInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pipeline*: VkPipeline - VkPipelineInfoEXT* = object - VkPipelineExecutablePropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - stages*: VkShaderStageFlags - name*: array[VK_MAX_DESCRIPTION_SIZE, char] - description*: array[VK_MAX_DESCRIPTION_SIZE, char] - subgroupSize*: uint32 - VkPipelineExecutableInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pipeline*: VkPipeline - executableIndex*: uint32 - VkPipelineExecutableStatisticValueKHR* {.union.} = object - b32*: VkBool32 - i64*: int64 - u64*: uint64 - f64*: float64 - VkPipelineExecutableStatisticKHR* = object - sType*: VkStructureType - pNext*: pointer - name*: array[VK_MAX_DESCRIPTION_SIZE, char] - description*: array[VK_MAX_DESCRIPTION_SIZE, char] - format*: VkPipelineExecutableStatisticFormatKHR - value*: VkPipelineExecutableStatisticValueKHR - VkPipelineExecutableInternalRepresentationKHR* = object - sType*: VkStructureType - pNext*: pointer - name*: array[VK_MAX_DESCRIPTION_SIZE, char] - description*: array[VK_MAX_DESCRIPTION_SIZE, char] - isText*: VkBool32 - dataSize*: csize_t - pData*: pointer - VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures* = object - sType*: VkStructureType - pNext*: pointer - shaderDemoteToHelperInvocation*: VkBool32 - VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT* = object - VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - texelBufferAlignment*: VkBool32 - VkPhysicalDeviceTexelBufferAlignmentProperties* = object - sType*: VkStructureType - pNext*: pointer - storageTexelBufferOffsetAlignmentBytes*: VkDeviceSize - storageTexelBufferOffsetSingleTexelAlignment*: VkBool32 - uniformTexelBufferOffsetAlignmentBytes*: VkDeviceSize - uniformTexelBufferOffsetSingleTexelAlignment*: VkBool32 - VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT* = object - VkPhysicalDeviceSubgroupSizeControlFeatures* = object - sType*: VkStructureType - pNext*: pointer - subgroupSizeControl*: VkBool32 - computeFullSubgroups*: VkBool32 - VkPhysicalDeviceSubgroupSizeControlFeaturesEXT* = object - VkPhysicalDeviceSubgroupSizeControlProperties* = object - sType*: VkStructureType - pNext*: pointer - minSubgroupSize*: uint32 - maxSubgroupSize*: uint32 - maxComputeWorkgroupSubgroups*: uint32 - requiredSubgroupSizeStages*: VkShaderStageFlags - VkPhysicalDeviceSubgroupSizeControlPropertiesEXT* = object - VkPipelineShaderStageRequiredSubgroupSizeCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - requiredSubgroupSize*: uint32 - VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT* = object - VkSubpassShadingPipelineCreateInfoHUAWEI* = object - sType*: VkStructureType - pNext*: pointer - renderPass*: VkRenderPass - subpass*: uint32 - VkPhysicalDeviceSubpassShadingPropertiesHUAWEI* = object - sType*: VkStructureType - pNext*: pointer - maxSubpassShadingWorkgroupSizeAspectRatio*: uint32 - VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI* = object - sType*: VkStructureType - pNext*: pointer - maxWorkGroupCount*: array[3, uint32] - maxWorkGroupSize*: array[3, uint32] - maxOutputClusterCount*: uint32 - VkMemoryOpaqueCaptureAddressAllocateInfo* = object - sType*: VkStructureType - pNext*: pointer - opaqueCaptureAddress*: uint64 - VkMemoryOpaqueCaptureAddressAllocateInfoKHR* = object - VkDeviceMemoryOpaqueCaptureAddressInfo* = object - sType*: VkStructureType - pNext*: pointer - memory*: VkDeviceMemory - VkDeviceMemoryOpaqueCaptureAddressInfoKHR* = object - VkPhysicalDeviceLineRasterizationFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - rectangularLines*: VkBool32 - bresenhamLines*: VkBool32 - smoothLines*: VkBool32 - stippledRectangularLines*: VkBool32 - stippledBresenhamLines*: VkBool32 - stippledSmoothLines*: VkBool32 - VkPhysicalDeviceLineRasterizationPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - lineSubPixelPrecisionBits*: uint32 - VkPipelineRasterizationLineStateCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - lineRasterizationMode*: VkLineRasterizationModeEXT - stippledLineEnable*: VkBool32 - lineStippleFactor*: uint32 - lineStipplePattern*: uint16 - VkPhysicalDevicePipelineCreationCacheControlFeatures* = object - sType*: VkStructureType - pNext*: pointer - pipelineCreationCacheControl*: VkBool32 - VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT* = object - VkPhysicalDeviceVulkan11Features* = object - sType*: VkStructureType - pNext*: pointer - storageBuffer16BitAccess*: VkBool32 - uniformAndStorageBuffer16BitAccess*: VkBool32 - storagePushConstant16*: VkBool32 - storageInputOutput16*: VkBool32 - multiview*: VkBool32 - multiviewGeometryShader*: VkBool32 - multiviewTessellationShader*: VkBool32 - variablePointersStorageBuffer*: VkBool32 - variablePointers*: VkBool32 - protectedMemory*: VkBool32 - samplerYcbcrConversion*: VkBool32 - shaderDrawParameters*: VkBool32 - VkPhysicalDeviceVulkan11Properties* = object - sType*: VkStructureType - pNext*: pointer - deviceUUID*: array[VK_UUID_SIZE, uint8] - driverUUID*: array[VK_UUID_SIZE, uint8] - deviceLUID*: array[VK_LUID_SIZE, uint8] - deviceNodeMask*: uint32 - deviceLUIDValid*: VkBool32 - subgroupSize*: uint32 - subgroupSupportedStages*: VkShaderStageFlags - subgroupSupportedOperations*: VkSubgroupFeatureFlags - subgroupQuadOperationsInAllStages*: VkBool32 - pointClippingBehavior*: VkPointClippingBehavior - maxMultiviewViewCount*: uint32 - maxMultiviewInstanceIndex*: uint32 - protectedNoFault*: VkBool32 - maxPerSetDescriptors*: uint32 - maxMemoryAllocationSize*: VkDeviceSize - VkPhysicalDeviceVulkan12Features* = object - sType*: VkStructureType - pNext*: pointer - samplerMirrorClampToEdge*: VkBool32 - drawIndirectCount*: VkBool32 - storageBuffer8BitAccess*: VkBool32 - uniformAndStorageBuffer8BitAccess*: VkBool32 - storagePushConstant8*: VkBool32 - shaderBufferInt64Atomics*: VkBool32 - shaderSharedInt64Atomics*: VkBool32 - shaderFloat16*: VkBool32 - shaderInt8*: VkBool32 - descriptorIndexing*: VkBool32 - shaderInputAttachmentArrayDynamicIndexing*: VkBool32 - shaderUniformTexelBufferArrayDynamicIndexing*: VkBool32 - shaderStorageTexelBufferArrayDynamicIndexing*: VkBool32 - shaderUniformBufferArrayNonUniformIndexing*: VkBool32 - shaderSampledImageArrayNonUniformIndexing*: VkBool32 - shaderStorageBufferArrayNonUniformIndexing*: VkBool32 - shaderStorageImageArrayNonUniformIndexing*: VkBool32 - shaderInputAttachmentArrayNonUniformIndexing*: VkBool32 - shaderUniformTexelBufferArrayNonUniformIndexing*: VkBool32 - shaderStorageTexelBufferArrayNonUniformIndexing*: VkBool32 - descriptorBindingUniformBufferUpdateAfterBind*: VkBool32 - descriptorBindingSampledImageUpdateAfterBind*: VkBool32 - descriptorBindingStorageImageUpdateAfterBind*: VkBool32 - descriptorBindingStorageBufferUpdateAfterBind*: VkBool32 - descriptorBindingUniformTexelBufferUpdateAfterBind*: VkBool32 - descriptorBindingStorageTexelBufferUpdateAfterBind*: VkBool32 - descriptorBindingUpdateUnusedWhilePending*: VkBool32 - descriptorBindingPartiallyBound*: VkBool32 - descriptorBindingVariableDescriptorCount*: VkBool32 - runtimeDescriptorArray*: VkBool32 - samplerFilterMinmax*: VkBool32 - scalarBlockLayout*: VkBool32 - imagelessFramebuffer*: VkBool32 - uniformBufferStandardLayout*: VkBool32 - shaderSubgroupExtendedTypes*: VkBool32 - separateDepthStencilLayouts*: VkBool32 - hostQueryReset*: VkBool32 - timelineSemaphore*: VkBool32 - bufferDeviceAddress*: VkBool32 - bufferDeviceAddressCaptureReplay*: VkBool32 - bufferDeviceAddressMultiDevice*: VkBool32 - vulkanMemoryModel*: VkBool32 - vulkanMemoryModelDeviceScope*: VkBool32 - vulkanMemoryModelAvailabilityVisibilityChains*: VkBool32 - shaderOutputViewportIndex*: VkBool32 - shaderOutputLayer*: VkBool32 - subgroupBroadcastDynamicId*: VkBool32 - VkPhysicalDeviceVulkan12Properties* = object - sType*: VkStructureType - pNext*: pointer - driverID*: VkDriverId - driverName*: array[VK_MAX_DRIVER_NAME_SIZE, char] - driverInfo*: array[VK_MAX_DRIVER_INFO_SIZE, char] - conformanceVersion*: VkConformanceVersion - denormBehaviorIndependence*: VkShaderFloatControlsIndependence - roundingModeIndependence*: VkShaderFloatControlsIndependence - shaderSignedZeroInfNanPreserveFloat16*: VkBool32 - shaderSignedZeroInfNanPreserveFloat32*: VkBool32 - shaderSignedZeroInfNanPreserveFloat64*: VkBool32 - shaderDenormPreserveFloat16*: VkBool32 - shaderDenormPreserveFloat32*: VkBool32 - shaderDenormPreserveFloat64*: VkBool32 - shaderDenormFlushToZeroFloat16*: VkBool32 - shaderDenormFlushToZeroFloat32*: VkBool32 - shaderDenormFlushToZeroFloat64*: VkBool32 - shaderRoundingModeRTEFloat16*: VkBool32 - shaderRoundingModeRTEFloat32*: VkBool32 - shaderRoundingModeRTEFloat64*: VkBool32 - shaderRoundingModeRTZFloat16*: VkBool32 - shaderRoundingModeRTZFloat32*: VkBool32 - shaderRoundingModeRTZFloat64*: VkBool32 - maxUpdateAfterBindDescriptorsInAllPools*: uint32 - shaderUniformBufferArrayNonUniformIndexingNative*: VkBool32 - shaderSampledImageArrayNonUniformIndexingNative*: VkBool32 - shaderStorageBufferArrayNonUniformIndexingNative*: VkBool32 - shaderStorageImageArrayNonUniformIndexingNative*: VkBool32 - shaderInputAttachmentArrayNonUniformIndexingNative*: VkBool32 - robustBufferAccessUpdateAfterBind*: VkBool32 - quadDivergentImplicitLod*: VkBool32 - maxPerStageDescriptorUpdateAfterBindSamplers*: uint32 - maxPerStageDescriptorUpdateAfterBindUniformBuffers*: uint32 - maxPerStageDescriptorUpdateAfterBindStorageBuffers*: uint32 - maxPerStageDescriptorUpdateAfterBindSampledImages*: uint32 - maxPerStageDescriptorUpdateAfterBindStorageImages*: uint32 - maxPerStageDescriptorUpdateAfterBindInputAttachments*: uint32 - maxPerStageUpdateAfterBindResources*: uint32 - maxDescriptorSetUpdateAfterBindSamplers*: uint32 - maxDescriptorSetUpdateAfterBindUniformBuffers*: uint32 - maxDescriptorSetUpdateAfterBindUniformBuffersDynamic*: uint32 - maxDescriptorSetUpdateAfterBindStorageBuffers*: uint32 - maxDescriptorSetUpdateAfterBindStorageBuffersDynamic*: uint32 - maxDescriptorSetUpdateAfterBindSampledImages*: uint32 - maxDescriptorSetUpdateAfterBindStorageImages*: uint32 - maxDescriptorSetUpdateAfterBindInputAttachments*: uint32 - supportedDepthResolveModes*: VkResolveModeFlags - supportedStencilResolveModes*: VkResolveModeFlags - independentResolveNone*: VkBool32 - independentResolve*: VkBool32 - filterMinmaxSingleComponentFormats*: VkBool32 - filterMinmaxImageComponentMapping*: VkBool32 - maxTimelineSemaphoreValueDifference*: uint64 - framebufferIntegerColorSampleCounts*: VkSampleCountFlags - VkPhysicalDeviceVulkan13Features* = object - sType*: VkStructureType - pNext*: pointer - robustImageAccess*: VkBool32 - inlineUniformBlock*: VkBool32 - descriptorBindingInlineUniformBlockUpdateAfterBind*: VkBool32 - pipelineCreationCacheControl*: VkBool32 - privateData*: VkBool32 - shaderDemoteToHelperInvocation*: VkBool32 - shaderTerminateInvocation*: VkBool32 - subgroupSizeControl*: VkBool32 - computeFullSubgroups*: VkBool32 - synchronization2*: VkBool32 - textureCompressionASTC_HDR*: VkBool32 - shaderZeroInitializeWorkgroupMemory*: VkBool32 - dynamicRendering*: VkBool32 - shaderIntegerDotProduct*: VkBool32 - maintenance4*: VkBool32 - VkPhysicalDeviceVulkan13Properties* = object - sType*: VkStructureType - pNext*: pointer - minSubgroupSize*: uint32 - maxSubgroupSize*: uint32 - maxComputeWorkgroupSubgroups*: uint32 - requiredSubgroupSizeStages*: VkShaderStageFlags - maxInlineUniformBlockSize*: uint32 - maxPerStageDescriptorInlineUniformBlocks*: uint32 - maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks*: uint32 - maxDescriptorSetInlineUniformBlocks*: uint32 - maxDescriptorSetUpdateAfterBindInlineUniformBlocks*: uint32 - maxInlineUniformTotalSize*: uint32 - integerDotProduct8BitUnsignedAccelerated*: VkBool32 - integerDotProduct8BitSignedAccelerated*: VkBool32 - integerDotProduct8BitMixedSignednessAccelerated*: VkBool32 - integerDotProduct4x8BitPackedUnsignedAccelerated*: VkBool32 - integerDotProduct4x8BitPackedSignedAccelerated*: VkBool32 - integerDotProduct4x8BitPackedMixedSignednessAccelerated*: VkBool32 - integerDotProduct16BitUnsignedAccelerated*: VkBool32 - integerDotProduct16BitSignedAccelerated*: VkBool32 - integerDotProduct16BitMixedSignednessAccelerated*: VkBool32 - integerDotProduct32BitUnsignedAccelerated*: VkBool32 - integerDotProduct32BitSignedAccelerated*: VkBool32 - integerDotProduct32BitMixedSignednessAccelerated*: VkBool32 - integerDotProduct64BitUnsignedAccelerated*: VkBool32 - integerDotProduct64BitSignedAccelerated*: VkBool32 - integerDotProduct64BitMixedSignednessAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating8BitUnsignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating8BitSignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating16BitUnsignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating16BitSignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating32BitUnsignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating32BitSignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating64BitUnsignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating64BitSignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated*: VkBool32 - storageTexelBufferOffsetAlignmentBytes*: VkDeviceSize - storageTexelBufferOffsetSingleTexelAlignment*: VkBool32 - uniformTexelBufferOffsetAlignmentBytes*: VkDeviceSize - uniformTexelBufferOffsetSingleTexelAlignment*: VkBool32 - maxBufferSize*: VkDeviceSize - VkPipelineCompilerControlCreateInfoAMD* = object - sType*: VkStructureType - pNext*: pointer - compilerControlFlags*: VkPipelineCompilerControlFlagsAMD - VkPhysicalDeviceCoherentMemoryFeaturesAMD* = object - sType*: VkStructureType - pNext*: pointer - deviceCoherentMemory*: VkBool32 - VkFaultData* = object - sType*: VkStructureType - pNext*: pointer - faultLevel*: VkFaultLevel - faultType*: VkFaultType - VkFaultCallbackInfo* = object - sType*: VkStructureType - pNext*: pointer - faultCount*: uint32 - pFaults*: ptr VkFaultData - pfnFaultCallback*: PFN_vkFaultCallbackFunction - VkPhysicalDeviceToolProperties* = object - sType*: VkStructureType - pNext*: pointer - name*: array[VK_MAX_EXTENSION_NAME_SIZE, char] - version*: array[VK_MAX_EXTENSION_NAME_SIZE, char] - purposes*: VkToolPurposeFlags - description*: array[VK_MAX_DESCRIPTION_SIZE, char] - layer*: array[VK_MAX_EXTENSION_NAME_SIZE, char] - VkPhysicalDeviceToolPropertiesEXT* = object - VkSamplerCustomBorderColorCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - customBorderColor*: VkClearColorValue - format*: VkFormat - VkPhysicalDeviceCustomBorderColorPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - maxCustomBorderColorSamplers*: uint32 - VkPhysicalDeviceCustomBorderColorFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - customBorderColors*: VkBool32 - customBorderColorWithoutFormat*: VkBool32 - VkSamplerBorderColorComponentMappingCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - components*: VkComponentMapping - srgb*: VkBool32 - VkPhysicalDeviceBorderColorSwizzleFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - borderColorSwizzle*: VkBool32 - borderColorSwizzleFromImage*: VkBool32 - VkDeviceOrHostAddressKHR* {.union.} = object - deviceAddress*: VkDeviceAddress - hostAddress*: pointer - VkDeviceOrHostAddressConstKHR* {.union.} = object - deviceAddress*: VkDeviceAddress - hostAddress*: pointer - VkAccelerationStructureGeometryTrianglesDataKHR* = object - sType*: VkStructureType - pNext*: pointer - vertexFormat*: VkFormat - vertexData*: VkDeviceOrHostAddressConstKHR - vertexStride*: VkDeviceSize - maxVertex*: uint32 - indexType*: VkIndexType - indexData*: VkDeviceOrHostAddressConstKHR - transformData*: VkDeviceOrHostAddressConstKHR - VkAccelerationStructureGeometryAabbsDataKHR* = object - sType*: VkStructureType - pNext*: pointer - data*: VkDeviceOrHostAddressConstKHR - stride*: VkDeviceSize - VkAccelerationStructureGeometryInstancesDataKHR* = object - sType*: VkStructureType - pNext*: pointer - arrayOfPointers*: VkBool32 - data*: VkDeviceOrHostAddressConstKHR - VkAccelerationStructureGeometryDataKHR* {.union.} = object - triangles*: VkAccelerationStructureGeometryTrianglesDataKHR - aabbs*: VkAccelerationStructureGeometryAabbsDataKHR - instances*: VkAccelerationStructureGeometryInstancesDataKHR - VkAccelerationStructureGeometryKHR* = object - sType*: VkStructureType - pNext*: pointer - geometryType*: VkGeometryTypeKHR - geometry*: VkAccelerationStructureGeometryDataKHR - flags*: VkGeometryFlagsKHR - VkAccelerationStructureBuildGeometryInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - thetype*: VkAccelerationStructureTypeKHR - flags*: VkBuildAccelerationStructureFlagsKHR - mode*: VkBuildAccelerationStructureModeKHR - srcAccelerationStructure*: VkAccelerationStructureKHR - dstAccelerationStructure*: VkAccelerationStructureKHR - geometryCount*: uint32 - pGeometries*: ptr VkAccelerationStructureGeometryKHR - ppGeometries*: ptr ptr VkAccelerationStructureGeometryKHR - scratchData*: VkDeviceOrHostAddressKHR - VkAccelerationStructureBuildRangeInfoKHR* = object - primitiveCount*: uint32 - primitiveOffset*: uint32 - firstVertex*: uint32 - transformOffset*: uint32 - VkAccelerationStructureCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - createFlags*: VkAccelerationStructureCreateFlagsKHR - buffer*: VkBuffer - offset*: VkDeviceSize - size*: VkDeviceSize - thetype*: VkAccelerationStructureTypeKHR - deviceAddress*: VkDeviceAddress - VkAabbPositionsKHR* = object - minX*: float32 - minY*: float32 - minZ*: float32 - maxX*: float32 - maxY*: float32 - maxZ*: float32 - VkAabbPositionsNV* = object - VkTransformMatrixKHR* = object - matrix*: array[3*4, float32] - VkTransformMatrixNV* = object - VkAccelerationStructureInstanceKHR* = object - transform*: VkTransformMatrixKHR - instanceCustomIndex*: uint32 - mask*: uint32 - instanceShaderBindingTableRecordOffset*: uint32 - flags*: VkGeometryInstanceFlagsKHR - accelerationStructureReference*: uint64 - VkAccelerationStructureInstanceNV* = object - VkAccelerationStructureDeviceAddressInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - accelerationStructure*: VkAccelerationStructureKHR - VkAccelerationStructureVersionInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pVersionData*: ptr uint8 - VkCopyAccelerationStructureInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - src*: VkAccelerationStructureKHR - dst*: VkAccelerationStructureKHR - mode*: VkCopyAccelerationStructureModeKHR - VkCopyAccelerationStructureToMemoryInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - src*: VkAccelerationStructureKHR - dst*: VkDeviceOrHostAddressKHR - mode*: VkCopyAccelerationStructureModeKHR - VkCopyMemoryToAccelerationStructureInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - src*: VkDeviceOrHostAddressConstKHR - dst*: VkAccelerationStructureKHR - mode*: VkCopyAccelerationStructureModeKHR - VkRayTracingPipelineInterfaceCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - maxPipelineRayPayloadSize*: uint32 - maxPipelineRayHitAttributeSize*: uint32 - VkPipelineLibraryCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - libraryCount*: uint32 - pLibraries*: ptr VkPipeline - VkRefreshObjectKHR* = object - objectType*: VkObjectType - objectHandle*: uint64 - flags*: VkRefreshObjectFlagsKHR - VkRefreshObjectListKHR* = object - sType*: VkStructureType - pNext*: pointer - objectCount*: uint32 - pObjects*: ptr VkRefreshObjectKHR - VkPhysicalDeviceExtendedDynamicStateFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - extendedDynamicState*: VkBool32 - VkPhysicalDeviceExtendedDynamicState2FeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - extendedDynamicState2*: VkBool32 - extendedDynamicState2LogicOp*: VkBool32 - extendedDynamicState2PatchControlPoints*: VkBool32 - VkPhysicalDeviceExtendedDynamicState3FeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - extendedDynamicState3TessellationDomainOrigin*: VkBool32 - extendedDynamicState3DepthClampEnable*: VkBool32 - extendedDynamicState3PolygonMode*: VkBool32 - extendedDynamicState3RasterizationSamples*: VkBool32 - extendedDynamicState3SampleMask*: VkBool32 - extendedDynamicState3AlphaToCoverageEnable*: VkBool32 - extendedDynamicState3AlphaToOneEnable*: VkBool32 - extendedDynamicState3LogicOpEnable*: VkBool32 - extendedDynamicState3ColorBlendEnable*: VkBool32 - extendedDynamicState3ColorBlendEquation*: VkBool32 - extendedDynamicState3ColorWriteMask*: VkBool32 - extendedDynamicState3RasterizationStream*: VkBool32 - extendedDynamicState3ConservativeRasterizationMode*: VkBool32 - extendedDynamicState3ExtraPrimitiveOverestimationSize*: VkBool32 - extendedDynamicState3DepthClipEnable*: VkBool32 - extendedDynamicState3SampleLocationsEnable*: VkBool32 - extendedDynamicState3ColorBlendAdvanced*: VkBool32 - extendedDynamicState3ProvokingVertexMode*: VkBool32 - extendedDynamicState3LineRasterizationMode*: VkBool32 - extendedDynamicState3LineStippleEnable*: VkBool32 - extendedDynamicState3DepthClipNegativeOneToOne*: VkBool32 - extendedDynamicState3ViewportWScalingEnable*: VkBool32 - extendedDynamicState3ViewportSwizzle*: VkBool32 - extendedDynamicState3CoverageToColorEnable*: VkBool32 - extendedDynamicState3CoverageToColorLocation*: VkBool32 - extendedDynamicState3CoverageModulationMode*: VkBool32 - extendedDynamicState3CoverageModulationTableEnable*: VkBool32 - extendedDynamicState3CoverageModulationTable*: VkBool32 - extendedDynamicState3CoverageReductionMode*: VkBool32 - extendedDynamicState3RepresentativeFragmentTestEnable*: VkBool32 - extendedDynamicState3ShadingRateImageEnable*: VkBool32 - VkPhysicalDeviceExtendedDynamicState3PropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - dynamicPrimitiveTopologyUnrestricted*: VkBool32 - VkColorBlendEquationEXT* = object - srcColorBlendFactor*: VkBlendFactor - dstColorBlendFactor*: VkBlendFactor - colorBlendOp*: VkBlendOp - srcAlphaBlendFactor*: VkBlendFactor - dstAlphaBlendFactor*: VkBlendFactor - alphaBlendOp*: VkBlendOp - VkColorBlendAdvancedEXT* = object - advancedBlendOp*: VkBlendOp - srcPremultiplied*: VkBool32 - dstPremultiplied*: VkBool32 - blendOverlap*: VkBlendOverlapEXT - clampResults*: VkBool32 - VkRenderPassTransformBeginInfoQCOM* = object - sType*: VkStructureType - pNext*: pointer - transform*: VkSurfaceTransformFlagBitsKHR - VkCopyCommandTransformInfoQCOM* = object - sType*: VkStructureType - pNext*: pointer - transform*: VkSurfaceTransformFlagBitsKHR - VkCommandBufferInheritanceRenderPassTransformInfoQCOM* = object - sType*: VkStructureType - pNext*: pointer - transform*: VkSurfaceTransformFlagBitsKHR - renderArea*: VkRect2D - VkPhysicalDeviceDiagnosticsConfigFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - diagnosticsConfig*: VkBool32 - VkDeviceDiagnosticsConfigCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDeviceDiagnosticsConfigFlagsNV - VkPipelineOfflineCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - pipelineIdentifier*: array[VK_UUID_SIZE, uint8] - matchControl*: VkPipelineMatchControl - poolEntrySize*: VkDeviceSize - VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures* = object - sType*: VkStructureType - pNext*: pointer - shaderZeroInitializeWorkgroupMemory*: VkBool32 - VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR* = object - VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - shaderSubgroupUniformControlFlow*: VkBool32 - VkPhysicalDeviceRobustness2FeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - robustBufferAccess2*: VkBool32 - robustImageAccess2*: VkBool32 - nullDescriptor*: VkBool32 - VkPhysicalDeviceRobustness2PropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - robustStorageBufferAccessSizeAlignment*: VkDeviceSize - robustUniformBufferAccessSizeAlignment*: VkDeviceSize - VkPhysicalDeviceImageRobustnessFeatures* = object - sType*: VkStructureType - pNext*: pointer - robustImageAccess*: VkBool32 - VkPhysicalDeviceImageRobustnessFeaturesEXT* = object - VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - workgroupMemoryExplicitLayout*: VkBool32 - workgroupMemoryExplicitLayoutScalarBlockLayout*: VkBool32 - workgroupMemoryExplicitLayout8BitAccess*: VkBool32 - workgroupMemoryExplicitLayout16BitAccess*: VkBool32 - VkPhysicalDevice4444FormatsFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - formatA4R4G4B4*: VkBool32 - formatA4B4G4R4*: VkBool32 - VkPhysicalDeviceSubpassShadingFeaturesHUAWEI* = object - sType*: VkStructureType - pNext*: pointer - subpassShading*: VkBool32 - VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI* = object - sType*: VkStructureType - pNext*: pointer - clustercullingShader*: VkBool32 - multiviewClusterCullingShader*: VkBool32 - VkBufferCopy2* = object - sType*: VkStructureType - pNext*: pointer - srcOffset*: VkDeviceSize - dstOffset*: VkDeviceSize - size*: VkDeviceSize - VkBufferCopy2KHR* = object - VkImageCopy2* = object - sType*: VkStructureType - pNext*: pointer - srcSubresource*: VkImageSubresourceLayers - srcOffset*: VkOffset3D - dstSubresource*: VkImageSubresourceLayers - dstOffset*: VkOffset3D - extent*: VkExtent3D - VkImageCopy2KHR* = object - VkImageBlit2* = object - sType*: VkStructureType - pNext*: pointer - srcSubresource*: VkImageSubresourceLayers - srcOffsets*: array[2, VkOffset3D] - dstSubresource*: VkImageSubresourceLayers - dstOffsets*: array[2, VkOffset3D] - VkImageBlit2KHR* = object - VkBufferImageCopy2* = object - sType*: VkStructureType - pNext*: pointer - bufferOffset*: VkDeviceSize - bufferRowLength*: uint32 - bufferImageHeight*: uint32 - imageSubresource*: VkImageSubresourceLayers - imageOffset*: VkOffset3D - imageExtent*: VkExtent3D - VkBufferImageCopy2KHR* = object - VkImageResolve2* = object - sType*: VkStructureType - pNext*: pointer - srcSubresource*: VkImageSubresourceLayers - srcOffset*: VkOffset3D - dstSubresource*: VkImageSubresourceLayers - dstOffset*: VkOffset3D - extent*: VkExtent3D - VkImageResolve2KHR* = object - VkCopyBufferInfo2* = object - sType*: VkStructureType - pNext*: pointer - srcBuffer*: VkBuffer - dstBuffer*: VkBuffer - regionCount*: uint32 - pRegions*: ptr VkBufferCopy2 - VkCopyBufferInfo2KHR* = object - VkCopyImageInfo2* = object - sType*: VkStructureType - pNext*: pointer - srcImage*: VkImage - srcImageLayout*: VkImageLayout - dstImage*: VkImage - dstImageLayout*: VkImageLayout - regionCount*: uint32 - pRegions*: ptr VkImageCopy2 - VkCopyImageInfo2KHR* = object - VkBlitImageInfo2* = object - sType*: VkStructureType - pNext*: pointer - srcImage*: VkImage - srcImageLayout*: VkImageLayout - dstImage*: VkImage - dstImageLayout*: VkImageLayout - regionCount*: uint32 - pRegions*: ptr VkImageBlit2 - filter*: VkFilter - VkBlitImageInfo2KHR* = object - VkCopyBufferToImageInfo2* = object - sType*: VkStructureType - pNext*: pointer - srcBuffer*: VkBuffer - dstImage*: VkImage - dstImageLayout*: VkImageLayout - regionCount*: uint32 - pRegions*: ptr VkBufferImageCopy2 - VkCopyBufferToImageInfo2KHR* = object - VkCopyImageToBufferInfo2* = object - sType*: VkStructureType - pNext*: pointer - srcImage*: VkImage - srcImageLayout*: VkImageLayout - dstBuffer*: VkBuffer - regionCount*: uint32 - pRegions*: ptr VkBufferImageCopy2 - VkCopyImageToBufferInfo2KHR* = object - VkResolveImageInfo2* = object - sType*: VkStructureType - pNext*: pointer - srcImage*: VkImage - srcImageLayout*: VkImageLayout - dstImage*: VkImage - dstImageLayout*: VkImageLayout - regionCount*: uint32 - pRegions*: ptr VkImageResolve2 - VkResolveImageInfo2KHR* = object - VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - shaderImageInt64Atomics*: VkBool32 - sparseImageInt64Atomics*: VkBool32 - VkFragmentShadingRateAttachmentInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pFragmentShadingRateAttachment*: ptr VkAttachmentReference2 - shadingRateAttachmentTexelSize*: VkExtent2D - VkPipelineFragmentShadingRateStateCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - fragmentSize*: VkExtent2D - combinerOps*: array[2, VkFragmentShadingRateCombinerOpKHR] - VkPhysicalDeviceFragmentShadingRateFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - pipelineFragmentShadingRate*: VkBool32 - primitiveFragmentShadingRate*: VkBool32 - attachmentFragmentShadingRate*: VkBool32 - VkPhysicalDeviceFragmentShadingRatePropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - minFragmentShadingRateAttachmentTexelSize*: VkExtent2D - maxFragmentShadingRateAttachmentTexelSize*: VkExtent2D - maxFragmentShadingRateAttachmentTexelSizeAspectRatio*: uint32 - primitiveFragmentShadingRateWithMultipleViewports*: VkBool32 - layeredShadingRateAttachments*: VkBool32 - fragmentShadingRateNonTrivialCombinerOps*: VkBool32 - maxFragmentSize*: VkExtent2D - maxFragmentSizeAspectRatio*: uint32 - maxFragmentShadingRateCoverageSamples*: uint32 - maxFragmentShadingRateRasterizationSamples*: VkSampleCountFlagBits - fragmentShadingRateWithShaderDepthStencilWrites*: VkBool32 - fragmentShadingRateWithSampleMask*: VkBool32 - fragmentShadingRateWithShaderSampleMask*: VkBool32 - fragmentShadingRateWithConservativeRasterization*: VkBool32 - fragmentShadingRateWithFragmentShaderInterlock*: VkBool32 - fragmentShadingRateWithCustomSampleLocations*: VkBool32 - fragmentShadingRateStrictMultiplyCombiner*: VkBool32 - VkPhysicalDeviceFragmentShadingRateKHR* = object - sType*: VkStructureType - pNext*: pointer - sampleCounts*: VkSampleCountFlags - fragmentSize*: VkExtent2D - VkPhysicalDeviceShaderTerminateInvocationFeatures* = object - sType*: VkStructureType - pNext*: pointer - shaderTerminateInvocation*: VkBool32 - VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR* = object - VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - fragmentShadingRateEnums*: VkBool32 - supersampleFragmentShadingRates*: VkBool32 - noInvocationFragmentShadingRates*: VkBool32 - VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - maxFragmentShadingRateInvocationCount*: VkSampleCountFlagBits - VkPipelineFragmentShadingRateEnumStateCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - shadingRateType*: VkFragmentShadingRateTypeNV - shadingRate*: VkFragmentShadingRateNV - combinerOps*: array[2, VkFragmentShadingRateCombinerOpKHR] - VkAccelerationStructureBuildSizesInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - accelerationStructureSize*: VkDeviceSize - updateScratchSize*: VkDeviceSize - buildScratchSize*: VkDeviceSize - VkPhysicalDeviceImage2DViewOf3DFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - image2DViewOf3D*: VkBool32 - sampler2DViewOf3D*: VkBool32 - VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - imageSlicedViewOf3D*: VkBool32 - VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - mutableDescriptorType*: VkBool32 - VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE* = object - VkMutableDescriptorTypeListEXT* = object - descriptorTypeCount*: uint32 - pDescriptorTypes*: ptr VkDescriptorType - VkMutableDescriptorTypeListVALVE* = object - VkMutableDescriptorTypeCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - mutableDescriptorTypeListCount*: uint32 - pMutableDescriptorTypeLists*: ptr VkMutableDescriptorTypeListEXT - VkMutableDescriptorTypeCreateInfoVALVE* = object - VkPhysicalDeviceDepthClipControlFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - depthClipControl*: VkBool32 - VkPipelineViewportDepthClipControlCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - negativeOneToOne*: VkBool32 - VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - vertexInputDynamicState*: VkBool32 - VkPhysicalDeviceExternalMemoryRDMAFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - externalMemoryRDMA*: VkBool32 - VkVertexInputBindingDescription2EXT* = object - sType*: VkStructureType - pNext*: pointer - binding*: uint32 - stride*: uint32 - inputRate*: VkVertexInputRate - divisor*: uint32 - VkVertexInputAttributeDescription2EXT* = object - sType*: VkStructureType - pNext*: pointer - location*: uint32 - binding*: uint32 - format*: VkFormat - offset*: uint32 - VkPhysicalDeviceColorWriteEnableFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - colorWriteEnable*: VkBool32 - VkPipelineColorWriteCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - attachmentCount*: uint32 - pColorWriteEnables*: ptr VkBool32 - VkMemoryBarrier2* = object - sType*: VkStructureType - pNext*: pointer - srcStageMask*: VkPipelineStageFlags2 - srcAccessMask*: VkAccessFlags2 - dstStageMask*: VkPipelineStageFlags2 - dstAccessMask*: VkAccessFlags2 - VkMemoryBarrier2KHR* = object - VkImageMemoryBarrier2* = object - sType*: VkStructureType - pNext*: pointer - srcStageMask*: VkPipelineStageFlags2 - srcAccessMask*: VkAccessFlags2 - dstStageMask*: VkPipelineStageFlags2 - dstAccessMask*: VkAccessFlags2 - oldLayout*: VkImageLayout - newLayout*: VkImageLayout - srcQueueFamilyIndex*: uint32 - dstQueueFamilyIndex*: uint32 - image*: VkImage - subresourceRange*: VkImageSubresourceRange - VkImageMemoryBarrier2KHR* = object - VkBufferMemoryBarrier2* = object - sType*: VkStructureType - pNext*: pointer - srcStageMask*: VkPipelineStageFlags2 - srcAccessMask*: VkAccessFlags2 - dstStageMask*: VkPipelineStageFlags2 - dstAccessMask*: VkAccessFlags2 - srcQueueFamilyIndex*: uint32 - dstQueueFamilyIndex*: uint32 - buffer*: VkBuffer - offset*: VkDeviceSize - size*: VkDeviceSize - VkBufferMemoryBarrier2KHR* = object - VkDependencyInfo* = object - sType*: VkStructureType - pNext*: pointer - dependencyFlags*: VkDependencyFlags - memoryBarrierCount*: uint32 - pMemoryBarriers*: ptr VkMemoryBarrier2 - bufferMemoryBarrierCount*: uint32 - pBufferMemoryBarriers*: ptr VkBufferMemoryBarrier2 - imageMemoryBarrierCount*: uint32 - pImageMemoryBarriers*: ptr VkImageMemoryBarrier2 - VkDependencyInfoKHR* = object - VkSemaphoreSubmitInfo* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - value*: uint64 - stageMask*: VkPipelineStageFlags2 - deviceIndex*: uint32 - VkSemaphoreSubmitInfoKHR* = object - VkCommandBufferSubmitInfo* = object - sType*: VkStructureType - pNext*: pointer - commandBuffer*: VkCommandBuffer - deviceMask*: uint32 - VkCommandBufferSubmitInfoKHR* = object - VkSubmitInfo2* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkSubmitFlags - waitSemaphoreInfoCount*: uint32 - pWaitSemaphoreInfos*: ptr VkSemaphoreSubmitInfo - commandBufferInfoCount*: uint32 - pCommandBufferInfos*: ptr VkCommandBufferSubmitInfo - signalSemaphoreInfoCount*: uint32 - pSignalSemaphoreInfos*: ptr VkSemaphoreSubmitInfo - VkSubmitInfo2KHR* = object - VkQueueFamilyCheckpointProperties2NV* = object - sType*: VkStructureType - pNext*: pointer - checkpointExecutionStageMask*: VkPipelineStageFlags2 - VkCheckpointData2NV* = object - sType*: VkStructureType - pNext*: pointer - stage*: VkPipelineStageFlags2 - pCheckpointMarker*: pointer - VkPhysicalDeviceSynchronization2Features* = object - sType*: VkStructureType - pNext*: pointer - synchronization2*: VkBool32 - VkPhysicalDeviceSynchronization2FeaturesKHR* = object - VkPhysicalDeviceVulkanSC10Properties* = object - sType*: VkStructureType - pNext*: pointer - deviceNoDynamicHostAllocations*: VkBool32 - deviceDestroyFreesMemory*: VkBool32 - commandPoolMultipleCommandBuffersRecording*: VkBool32 - commandPoolResetCommandBuffer*: VkBool32 - commandBufferSimultaneousUse*: VkBool32 - secondaryCommandBufferNullOrImagelessFramebuffer*: VkBool32 - recycleDescriptorSetMemory*: VkBool32 - recyclePipelineMemory*: VkBool32 - maxRenderPassSubpasses*: uint32 - maxRenderPassDependencies*: uint32 - maxSubpassInputAttachments*: uint32 - maxSubpassPreserveAttachments*: uint32 - maxFramebufferAttachments*: uint32 - maxDescriptorSetLayoutBindings*: uint32 - maxQueryFaultCount*: uint32 - maxCallbackFaultCount*: uint32 - maxCommandPoolCommandBuffers*: uint32 - maxCommandBufferSize*: VkDeviceSize - VkPipelinePoolSize* = object - sType*: VkStructureType - pNext*: pointer - poolEntrySize*: VkDeviceSize - poolEntryCount*: uint32 - VkDeviceObjectReservationCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - pipelineCacheCreateInfoCount*: uint32 - pPipelineCacheCreateInfos*: ptr VkPipelineCacheCreateInfo - pipelinePoolSizeCount*: uint32 - pPipelinePoolSizes*: ptr VkPipelinePoolSize - semaphoreRequestCount*: uint32 - commandBufferRequestCount*: uint32 - fenceRequestCount*: uint32 - deviceMemoryRequestCount*: uint32 - bufferRequestCount*: uint32 - imageRequestCount*: uint32 - eventRequestCount*: uint32 - queryPoolRequestCount*: uint32 - bufferViewRequestCount*: uint32 - imageViewRequestCount*: uint32 - layeredImageViewRequestCount*: uint32 - pipelineCacheRequestCount*: uint32 - pipelineLayoutRequestCount*: uint32 - renderPassRequestCount*: uint32 - graphicsPipelineRequestCount*: uint32 - computePipelineRequestCount*: uint32 - descriptorSetLayoutRequestCount*: uint32 - samplerRequestCount*: uint32 - descriptorPoolRequestCount*: uint32 - descriptorSetRequestCount*: uint32 - framebufferRequestCount*: uint32 - commandPoolRequestCount*: uint32 - samplerYcbcrConversionRequestCount*: uint32 - surfaceRequestCount*: uint32 - swapchainRequestCount*: uint32 - displayModeRequestCount*: uint32 - subpassDescriptionRequestCount*: uint32 - attachmentDescriptionRequestCount*: uint32 - descriptorSetLayoutBindingRequestCount*: uint32 - descriptorSetLayoutBindingLimit*: uint32 - maxImageViewMipLevels*: uint32 - maxImageViewArrayLayers*: uint32 - maxLayeredImageViewMipLevels*: uint32 - maxOcclusionQueriesPerPool*: uint32 - maxPipelineStatisticsQueriesPerPool*: uint32 - maxTimestampQueriesPerPool*: uint32 - maxImmutableSamplersPerDescriptorSetLayout*: uint32 - VkCommandPoolMemoryReservationCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - commandPoolReservedSize*: VkDeviceSize - commandPoolMaxCommandBuffers*: uint32 - VkCommandPoolMemoryConsumption* = object - sType*: VkStructureType - pNext*: pointer - commandPoolAllocated*: VkDeviceSize - commandPoolReservedSize*: VkDeviceSize - commandBufferAllocated*: VkDeviceSize - VkPhysicalDeviceVulkanSC10Features* = object - sType*: VkStructureType - pNext*: pointer - shaderAtomicInstructions*: VkBool32 - VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - primitivesGeneratedQuery*: VkBool32 - primitivesGeneratedQueryWithRasterizerDiscard*: VkBool32 - primitivesGeneratedQueryWithNonZeroStreams*: VkBool32 - VkPhysicalDeviceLegacyDitheringFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - legacyDithering*: VkBool32 - VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - multisampledRenderToSingleSampled*: VkBool32 - VkSubpassResolvePerformanceQueryEXT* = object - sType*: VkStructureType - pNext*: pointer - optimal*: VkBool32 - VkMultisampledRenderToSingleSampledInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - multisampledRenderToSingleSampledEnable*: VkBool32 - rasterizationSamples*: VkSampleCountFlagBits - VkPhysicalDevicePipelineProtectedAccessFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - pipelineProtectedAccess*: VkBool32 - VkPhysicalDeviceInheritedViewportScissorFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - inheritedViewportScissor2D*: VkBool32 - VkCommandBufferInheritanceViewportScissorInfoNV* = object - sType*: VkStructureType - pNext*: pointer - viewportScissor2D*: VkBool32 - viewportDepthCount*: uint32 - pViewportDepths*: ptr VkViewport - VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - ycbcr2plane444Formats*: VkBool32 - VkPhysicalDeviceProvokingVertexFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - provokingVertexLast*: VkBool32 - transformFeedbackPreservesProvokingVertex*: VkBool32 - VkPhysicalDeviceProvokingVertexPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - provokingVertexModePerPipeline*: VkBool32 - transformFeedbackPreservesTriangleFanProvokingVertex*: VkBool32 - VkPipelineRasterizationProvokingVertexStateCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - provokingVertexMode*: VkProvokingVertexModeEXT - VkCuModuleCreateInfoNVX* = object - sType*: VkStructureType - pNext*: pointer - dataSize*: csize_t - pData*: pointer - VkCuFunctionCreateInfoNVX* = object - sType*: VkStructureType - pNext*: pointer - module*: VkCuModuleNVX - pName*: cstring - VkCuLaunchInfoNVX* = object - sType*: VkStructureType - pNext*: pointer - function*: VkCuFunctionNVX - gridDimX*: uint32 - gridDimY*: uint32 - gridDimZ*: uint32 - blockDimX*: uint32 - blockDimY*: uint32 - blockDimZ*: uint32 - sharedMemBytes*: uint32 - paramCount*: csize_t - pParams*: ptr pointer - extraCount*: csize_t - pExtras*: ptr pointer - VkPhysicalDeviceDescriptorBufferFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - descriptorBuffer*: VkBool32 - descriptorBufferCaptureReplay*: VkBool32 - descriptorBufferImageLayoutIgnored*: VkBool32 - descriptorBufferPushDescriptors*: VkBool32 - VkPhysicalDeviceDescriptorBufferPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - combinedImageSamplerDescriptorSingleArray*: VkBool32 - bufferlessPushDescriptors*: VkBool32 - allowSamplerImageViewPostSubmitCreation*: VkBool32 - descriptorBufferOffsetAlignment*: VkDeviceSize - maxDescriptorBufferBindings*: uint32 - maxResourceDescriptorBufferBindings*: uint32 - maxSamplerDescriptorBufferBindings*: uint32 - maxEmbeddedImmutableSamplerBindings*: uint32 - maxEmbeddedImmutableSamplers*: uint32 - bufferCaptureReplayDescriptorDataSize*: csize_t - imageCaptureReplayDescriptorDataSize*: csize_t - imageViewCaptureReplayDescriptorDataSize*: csize_t - samplerCaptureReplayDescriptorDataSize*: csize_t - accelerationStructureCaptureReplayDescriptorDataSize*: csize_t - samplerDescriptorSize*: csize_t - combinedImageSamplerDescriptorSize*: csize_t - sampledImageDescriptorSize*: csize_t - storageImageDescriptorSize*: csize_t - uniformTexelBufferDescriptorSize*: csize_t - robustUniformTexelBufferDescriptorSize*: csize_t - storageTexelBufferDescriptorSize*: csize_t - robustStorageTexelBufferDescriptorSize*: csize_t - uniformBufferDescriptorSize*: csize_t - robustUniformBufferDescriptorSize*: csize_t - storageBufferDescriptorSize*: csize_t - robustStorageBufferDescriptorSize*: csize_t - inputAttachmentDescriptorSize*: csize_t - accelerationStructureDescriptorSize*: csize_t - maxSamplerDescriptorBufferRange*: VkDeviceSize - maxResourceDescriptorBufferRange*: VkDeviceSize - samplerDescriptorBufferAddressSpaceSize*: VkDeviceSize - resourceDescriptorBufferAddressSpaceSize*: VkDeviceSize - descriptorBufferAddressSpaceSize*: VkDeviceSize - VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - combinedImageSamplerDensityMapDescriptorSize*: csize_t - VkDescriptorAddressInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - address*: VkDeviceAddress - range*: VkDeviceSize - format*: VkFormat - VkDescriptorBufferBindingInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - address*: VkDeviceAddress - usage*: VkBufferUsageFlags - VkDescriptorBufferBindingPushDescriptorBufferHandleEXT* = object - sType*: VkStructureType - pNext*: pointer - buffer*: VkBuffer - VkDescriptorDataEXT* {.union.} = object - pSampler*: ptr VkSampler - pCombinedImageSampler*: ptr VkDescriptorImageInfo - pInputAttachmentImage*: ptr VkDescriptorImageInfo - pSampledImage*: ptr VkDescriptorImageInfo - pStorageImage*: ptr VkDescriptorImageInfo - pUniformTexelBuffer*: ptr VkDescriptorAddressInfoEXT - pStorageTexelBuffer*: ptr VkDescriptorAddressInfoEXT - pUniformBuffer*: ptr VkDescriptorAddressInfoEXT - pStorageBuffer*: ptr VkDescriptorAddressInfoEXT - accelerationStructure*: VkDeviceAddress - VkDescriptorGetInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - thetype*: VkDescriptorType - data*: VkDescriptorDataEXT - VkBufferCaptureDescriptorDataInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - buffer*: VkBuffer - VkImageCaptureDescriptorDataInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - image*: VkImage - VkImageViewCaptureDescriptorDataInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - imageView*: VkImageView - VkSamplerCaptureDescriptorDataInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - sampler*: VkSampler - VkAccelerationStructureCaptureDescriptorDataInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - accelerationStructure*: VkAccelerationStructureKHR - accelerationStructureNV*: VkAccelerationStructureNV - VkOpaqueCaptureDescriptorDataCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - opaqueCaptureDescriptorData*: pointer - VkPhysicalDeviceShaderIntegerDotProductFeatures* = object - sType*: VkStructureType - pNext*: pointer - shaderIntegerDotProduct*: VkBool32 - VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR* = object - VkPhysicalDeviceShaderIntegerDotProductProperties* = object - sType*: VkStructureType - pNext*: pointer - integerDotProduct8BitUnsignedAccelerated*: VkBool32 - integerDotProduct8BitSignedAccelerated*: VkBool32 - integerDotProduct8BitMixedSignednessAccelerated*: VkBool32 - integerDotProduct4x8BitPackedUnsignedAccelerated*: VkBool32 - integerDotProduct4x8BitPackedSignedAccelerated*: VkBool32 - integerDotProduct4x8BitPackedMixedSignednessAccelerated*: VkBool32 - integerDotProduct16BitUnsignedAccelerated*: VkBool32 - integerDotProduct16BitSignedAccelerated*: VkBool32 - integerDotProduct16BitMixedSignednessAccelerated*: VkBool32 - integerDotProduct32BitUnsignedAccelerated*: VkBool32 - integerDotProduct32BitSignedAccelerated*: VkBool32 - integerDotProduct32BitMixedSignednessAccelerated*: VkBool32 - integerDotProduct64BitUnsignedAccelerated*: VkBool32 - integerDotProduct64BitSignedAccelerated*: VkBool32 - integerDotProduct64BitMixedSignednessAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating8BitUnsignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating8BitSignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating16BitUnsignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating16BitSignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating32BitUnsignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating32BitSignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating64BitUnsignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating64BitSignedAccelerated*: VkBool32 - integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated*: VkBool32 - VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR* = object - VkPhysicalDeviceDrmPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - hasPrimary*: VkBool32 - hasRender*: VkBool32 - primaryMajor*: int64 - primaryMinor*: int64 - renderMajor*: int64 - renderMinor*: int64 - VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - fragmentShaderBarycentric*: VkBool32 - VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - triStripVertexOrderIndependentOfProvokingVertex*: VkBool32 - VkPhysicalDeviceRayTracingMotionBlurFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - rayTracingMotionBlur*: VkBool32 - rayTracingMotionBlurPipelineTraceRaysIndirect*: VkBool32 - VkAccelerationStructureGeometryMotionTrianglesDataNV* = object - sType*: VkStructureType - pNext*: pointer - vertexData*: VkDeviceOrHostAddressConstKHR - VkAccelerationStructureMotionInfoNV* = object - sType*: VkStructureType - pNext*: pointer - maxInstances*: uint32 - flags*: VkAccelerationStructureMotionInfoFlagsNV - VkSRTDataNV* = object - sx*: float32 - a*: float32 - b*: float32 - pvx*: float32 - sy*: float32 - c*: float32 - pvy*: float32 - sz*: float32 - pvz*: float32 - qx*: float32 - qy*: float32 - qz*: float32 - qw*: float32 - tx*: float32 - ty*: float32 - tz*: float32 - VkAccelerationStructureSRTMotionInstanceNV* = object - transformT0*: VkSRTDataNV - transformT1*: VkSRTDataNV - instanceCustomIndex*: uint32 - mask*: uint32 - instanceShaderBindingTableRecordOffset*: uint32 - flags*: VkGeometryInstanceFlagsKHR - accelerationStructureReference*: uint64 - VkAccelerationStructureMatrixMotionInstanceNV* = object - transformT0*: VkTransformMatrixKHR - transformT1*: VkTransformMatrixKHR - instanceCustomIndex*: uint32 - mask*: uint32 - instanceShaderBindingTableRecordOffset*: uint32 - flags*: VkGeometryInstanceFlagsKHR - accelerationStructureReference*: uint64 - VkAccelerationStructureMotionInstanceDataNV* {.union.} = object - staticInstance*: VkAccelerationStructureInstanceKHR - matrixMotionInstance*: VkAccelerationStructureMatrixMotionInstanceNV - srtMotionInstance*: VkAccelerationStructureSRTMotionInstanceNV - VkAccelerationStructureMotionInstanceNV* = object - thetype*: VkAccelerationStructureMotionInstanceTypeNV - flags*: VkAccelerationStructureMotionInstanceFlagsNV - data*: VkAccelerationStructureMotionInstanceDataNV - VkMemoryGetRemoteAddressInfoNV* = object - sType*: VkStructureType - pNext*: pointer - memory*: VkDeviceMemory - handleType*: VkExternalMemoryHandleTypeFlagBits - VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - formatRgba10x6WithoutYCbCrSampler*: VkBool32 - VkFormatProperties3* = object - sType*: VkStructureType - pNext*: pointer - linearTilingFeatures*: VkFormatFeatureFlags2 - optimalTilingFeatures*: VkFormatFeatureFlags2 - bufferFeatures*: VkFormatFeatureFlags2 - VkFormatProperties3KHR* = object - VkDrmFormatModifierPropertiesList2EXT* = object - sType*: VkStructureType - pNext*: pointer - drmFormatModifierCount*: uint32 - pDrmFormatModifierProperties*: ptr VkDrmFormatModifierProperties2EXT - VkDrmFormatModifierProperties2EXT* = object - drmFormatModifier*: uint64 - drmFormatModifierPlaneCount*: uint32 - drmFormatModifierTilingFeatures*: VkFormatFeatureFlags2 - VkPipelineRenderingCreateInfo* = object - sType*: VkStructureType - pNext*: pointer - viewMask*: uint32 - colorAttachmentCount*: uint32 - pColorAttachmentFormats*: ptr VkFormat - depthAttachmentFormat*: VkFormat - stencilAttachmentFormat*: VkFormat - VkPipelineRenderingCreateInfoKHR* = object - VkRenderingInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkRenderingFlags - renderArea*: VkRect2D - layerCount*: uint32 - viewMask*: uint32 - colorAttachmentCount*: uint32 - pColorAttachments*: ptr VkRenderingAttachmentInfo - pDepthAttachment*: ptr VkRenderingAttachmentInfo - pStencilAttachment*: ptr VkRenderingAttachmentInfo - VkRenderingInfoKHR* = object - VkRenderingAttachmentInfo* = object - sType*: VkStructureType - pNext*: pointer - imageView*: VkImageView - imageLayout*: VkImageLayout - resolveMode*: VkResolveModeFlagBits - resolveImageView*: VkImageView - resolveImageLayout*: VkImageLayout - loadOp*: VkAttachmentLoadOp - storeOp*: VkAttachmentStoreOp - clearValue*: VkClearValue - VkRenderingAttachmentInfoKHR* = object - VkRenderingFragmentShadingRateAttachmentInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - imageView*: VkImageView - imageLayout*: VkImageLayout - shadingRateAttachmentTexelSize*: VkExtent2D - VkRenderingFragmentDensityMapAttachmentInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - imageView*: VkImageView - imageLayout*: VkImageLayout - VkPhysicalDeviceDynamicRenderingFeatures* = object - sType*: VkStructureType - pNext*: pointer - dynamicRendering*: VkBool32 - VkPhysicalDeviceDynamicRenderingFeaturesKHR* = object - VkCommandBufferInheritanceRenderingInfo* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkRenderingFlags - viewMask*: uint32 - colorAttachmentCount*: uint32 - pColorAttachmentFormats*: ptr VkFormat - depthAttachmentFormat*: VkFormat - stencilAttachmentFormat*: VkFormat - rasterizationSamples*: VkSampleCountFlagBits - VkCommandBufferInheritanceRenderingInfoKHR* = object - VkAttachmentSampleCountInfoAMD* = object - sType*: VkStructureType - pNext*: pointer - colorAttachmentCount*: uint32 - pColorAttachmentSamples*: ptr VkSampleCountFlagBits - depthStencilAttachmentSamples*: VkSampleCountFlagBits - VkAttachmentSampleCountInfoNV* = object - VkMultiviewPerViewAttributesInfoNVX* = object - sType*: VkStructureType - pNext*: pointer - perViewAttributes*: VkBool32 - perViewAttributesPositionXOnly*: VkBool32 - VkPhysicalDeviceImageViewMinLodFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - minLod*: VkBool32 - VkImageViewMinLodCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - minLod*: float32 - VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - rasterizationOrderColorAttachmentAccess*: VkBool32 - rasterizationOrderDepthAttachmentAccess*: VkBool32 - rasterizationOrderStencilAttachmentAccess*: VkBool32 - VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM* = object - VkPhysicalDeviceLinearColorAttachmentFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - linearColorAttachment*: VkBool32 - VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - graphicsPipelineLibrary*: VkBool32 - VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - graphicsPipelineLibraryFastLinking*: VkBool32 - graphicsPipelineLibraryIndependentInterpolationDecoration*: VkBool32 - VkGraphicsPipelineLibraryCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkGraphicsPipelineLibraryFlagsEXT - VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE* = object - sType*: VkStructureType - pNext*: pointer - descriptorSetHostMapping*: VkBool32 - VkDescriptorSetBindingReferenceVALVE* = object - sType*: VkStructureType - pNext*: pointer - descriptorSetLayout*: VkDescriptorSetLayout - binding*: uint32 - VkDescriptorSetLayoutHostMappingInfoVALVE* = object - sType*: VkStructureType - pNext*: pointer - descriptorOffset*: csize_t - descriptorSize*: uint32 - VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - shaderModuleIdentifier*: VkBool32 - VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - shaderModuleIdentifierAlgorithmUUID*: array[VK_UUID_SIZE, uint8] - VkPipelineShaderStageModuleIdentifierCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - identifierSize*: uint32 - pIdentifier*: ptr uint8 - VkShaderModuleIdentifierEXT* = object - sType*: VkStructureType - pNext*: pointer - identifierSize*: uint32 - identifier*: array[VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT, uint8] - VkImageCompressionControlEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkImageCompressionFlagsEXT - compressionControlPlaneCount*: uint32 - pFixedRateFlags*: ptr VkImageCompressionFixedRateFlagsEXT - VkPhysicalDeviceImageCompressionControlFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - imageCompressionControl*: VkBool32 - VkImageCompressionPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - imageCompressionFlags*: VkImageCompressionFlagsEXT - imageCompressionFixedRateFlags*: VkImageCompressionFixedRateFlagsEXT - VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - imageCompressionControlSwapchain*: VkBool32 - VkImageSubresource2EXT* = object - sType*: VkStructureType - pNext*: pointer - imageSubresource*: VkImageSubresource - VkSubresourceLayout2EXT* = object - sType*: VkStructureType - pNext*: pointer - subresourceLayout*: VkSubresourceLayout - VkRenderPassCreationControlEXT* = object - sType*: VkStructureType - pNext*: pointer - disallowMerging*: VkBool32 - VkRenderPassCreationFeedbackInfoEXT* = object - postMergeSubpassCount*: uint32 - VkRenderPassCreationFeedbackCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - pRenderPassFeedback*: ptr VkRenderPassCreationFeedbackInfoEXT - VkRenderPassSubpassFeedbackInfoEXT* = object - subpassMergeStatus*: VkSubpassMergeStatusEXT - description*: array[VK_MAX_DESCRIPTION_SIZE, char] - postMergeIndex*: uint32 - VkRenderPassSubpassFeedbackCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - pSubpassFeedback*: ptr VkRenderPassSubpassFeedbackInfoEXT - VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - subpassMergeFeedback*: VkBool32 - VkMicromapBuildInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - thetype*: VkMicromapTypeEXT - flags*: VkBuildMicromapFlagsEXT - mode*: VkBuildMicromapModeEXT - dstMicromap*: VkMicromapEXT - usageCountsCount*: uint32 - pUsageCounts*: ptr VkMicromapUsageEXT - ppUsageCounts*: ptr ptr VkMicromapUsageEXT - data*: VkDeviceOrHostAddressConstKHR - scratchData*: VkDeviceOrHostAddressKHR - triangleArray*: VkDeviceOrHostAddressConstKHR - triangleArrayStride*: VkDeviceSize - VkMicromapCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - createFlags*: VkMicromapCreateFlagsEXT - buffer*: VkBuffer - offset*: VkDeviceSize - size*: VkDeviceSize - thetype*: VkMicromapTypeEXT - deviceAddress*: VkDeviceAddress - VkMicromapVersionInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - pVersionData*: ptr uint8 - VkCopyMicromapInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - src*: VkMicromapEXT - dst*: VkMicromapEXT - mode*: VkCopyMicromapModeEXT - VkCopyMicromapToMemoryInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - src*: VkMicromapEXT - dst*: VkDeviceOrHostAddressKHR - mode*: VkCopyMicromapModeEXT - VkCopyMemoryToMicromapInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - src*: VkDeviceOrHostAddressConstKHR - dst*: VkMicromapEXT - mode*: VkCopyMicromapModeEXT - VkMicromapBuildSizesInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - micromapSize*: VkDeviceSize - buildScratchSize*: VkDeviceSize - discardable*: VkBool32 - VkMicromapUsageEXT* = object - count*: uint32 - subdivisionLevel*: uint32 - format*: uint32 - VkMicromapTriangleEXT* = object - dataOffset*: uint32 - subdivisionLevel*: uint16 - format*: uint16 - VkPhysicalDeviceOpacityMicromapFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - micromap*: VkBool32 - micromapCaptureReplay*: VkBool32 - micromapHostCommands*: VkBool32 - VkPhysicalDeviceOpacityMicromapPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - maxOpacity2StateSubdivisionLevel*: uint32 - maxOpacity4StateSubdivisionLevel*: uint32 - VkAccelerationStructureTrianglesOpacityMicromapEXT* = object - sType*: VkStructureType - pNext*: pointer - indexType*: VkIndexType - indexBuffer*: VkDeviceOrHostAddressConstKHR - indexStride*: VkDeviceSize - baseTriangle*: uint32 - usageCountsCount*: uint32 - pUsageCounts*: ptr VkMicromapUsageEXT - ppUsageCounts*: ptr ptr VkMicromapUsageEXT - micromap*: VkMicromapEXT - VkPipelinePropertiesIdentifierEXT* = object - sType*: VkStructureType - pNext*: pointer - pipelineIdentifier*: array[VK_UUID_SIZE, uint8] - VkPhysicalDevicePipelinePropertiesFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - pipelinePropertiesIdentifier*: VkBool32 - VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD* = object - sType*: VkStructureType - pNext*: pointer - shaderEarlyAndLateFragmentTests*: VkBool32 - VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - nonSeamlessCubeMap*: VkBool32 - VkPhysicalDevicePipelineRobustnessFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - pipelineRobustness*: VkBool32 - VkPipelineRobustnessCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - storageBuffers*: VkPipelineRobustnessBufferBehaviorEXT - uniformBuffers*: VkPipelineRobustnessBufferBehaviorEXT - vertexInputs*: VkPipelineRobustnessBufferBehaviorEXT - images*: VkPipelineRobustnessImageBehaviorEXT - VkPhysicalDevicePipelineRobustnessPropertiesEXT* = object - sType*: VkStructureType - pNext*: pointer - defaultRobustnessStorageBuffers*: VkPipelineRobustnessBufferBehaviorEXT - defaultRobustnessUniformBuffers*: VkPipelineRobustnessBufferBehaviorEXT - defaultRobustnessVertexInputs*: VkPipelineRobustnessBufferBehaviorEXT - defaultRobustnessImages*: VkPipelineRobustnessImageBehaviorEXT - VkImageViewSampleWeightCreateInfoQCOM* = object - sType*: VkStructureType - pNext*: pointer - filterCenter*: VkOffset2D - filterSize*: VkExtent2D - numPhases*: uint32 - VkPhysicalDeviceImageProcessingFeaturesQCOM* = object - sType*: VkStructureType - pNext*: pointer - textureSampleWeighted*: VkBool32 - textureBoxFilter*: VkBool32 - textureBlockMatch*: VkBool32 - VkPhysicalDeviceImageProcessingPropertiesQCOM* = object - sType*: VkStructureType - pNext*: pointer - maxWeightFilterPhases*: uint32 - maxWeightFilterDimension*: VkExtent2D - maxBlockMatchRegion*: VkExtent2D - maxBoxFilterBlockSize*: VkExtent2D - VkPhysicalDeviceTilePropertiesFeaturesQCOM* = object - sType*: VkStructureType - pNext*: pointer - tileProperties*: VkBool32 - VkTilePropertiesQCOM* = object - sType*: VkStructureType - pNext*: pointer - tileSize*: VkExtent3D - apronSize*: VkExtent2D - origin*: VkOffset2D - VkPhysicalDeviceAmigoProfilingFeaturesSEC* = object - sType*: VkStructureType - pNext*: pointer - amigoProfiling*: VkBool32 - VkAmigoProfilingSubmitInfoSEC* = object - sType*: VkStructureType - pNext*: pointer - firstDrawTimestamp*: uint64 - swapBufferTimestamp*: uint64 - VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - attachmentFeedbackLoopLayout*: VkBool32 - VkPhysicalDeviceDepthClampZeroOneFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - depthClampZeroOne*: VkBool32 - VkPhysicalDeviceAddressBindingReportFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - reportAddressBinding*: VkBool32 - VkDeviceAddressBindingCallbackDataEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDeviceAddressBindingFlagsEXT - baseAddress*: VkDeviceAddress - size*: VkDeviceSize - bindingType*: VkDeviceAddressBindingTypeEXT - VkPhysicalDeviceOpticalFlowFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - opticalFlow*: VkBool32 - VkPhysicalDeviceOpticalFlowPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - supportedOutputGridSizes*: VkOpticalFlowGridSizeFlagsNV - supportedHintGridSizes*: VkOpticalFlowGridSizeFlagsNV - hintSupported*: VkBool32 - costSupported*: VkBool32 - bidirectionalFlowSupported*: VkBool32 - globalFlowSupported*: VkBool32 - minWidth*: uint32 - minHeight*: uint32 - maxWidth*: uint32 - maxHeight*: uint32 - maxNumRegionsOfInterest*: uint32 - VkOpticalFlowImageFormatInfoNV* = object - sType*: VkStructureType - pNext*: pointer - usage*: VkOpticalFlowUsageFlagsNV - VkOpticalFlowImageFormatPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - format*: VkFormat - VkOpticalFlowSessionCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - width*: uint32 - height*: uint32 - imageFormat*: VkFormat - flowVectorFormat*: VkFormat - costFormat*: VkFormat - outputGridSize*: VkOpticalFlowGridSizeFlagsNV - hintGridSize*: VkOpticalFlowGridSizeFlagsNV - performanceLevel*: VkOpticalFlowPerformanceLevelNV - flags*: VkOpticalFlowSessionCreateFlagsNV - VkOpticalFlowSessionCreatePrivateDataInfoNV* = object - sType*: VkStructureType - pNext*: pointer - id*: uint32 - size*: uint32 - pPrivateData*: pointer - VkOpticalFlowExecuteInfoNV* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkOpticalFlowExecuteFlagsNV - regionCount*: uint32 - pRegions*: ptr VkRect2D - VkPhysicalDeviceFaultFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - deviceFault*: VkBool32 - deviceFaultVendorBinary*: VkBool32 - VkDeviceFaultAddressInfoEXT* = object - addressType*: VkDeviceFaultAddressTypeEXT - reportedAddress*: VkDeviceAddress - addressPrecision*: VkDeviceSize - VkDeviceFaultVendorInfoEXT* = object - description*: array[VK_MAX_DESCRIPTION_SIZE, char] - vendorFaultCode*: uint64 - vendorFaultData*: uint64 - VkDeviceFaultCountsEXT* = object - sType*: VkStructureType - pNext*: pointer - addressInfoCount*: uint32 - vendorInfoCount*: uint32 - vendorBinarySize*: VkDeviceSize - VkDeviceFaultInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - description*: array[VK_MAX_DESCRIPTION_SIZE, char] - pAddressInfos*: ptr VkDeviceFaultAddressInfoEXT - pVendorInfos*: ptr VkDeviceFaultVendorInfoEXT - pVendorBinaryData*: pointer - VkDeviceFaultVendorBinaryHeaderVersionOneEXT* = object - headerSize*: uint32 - headerVersion*: VkDeviceFaultVendorBinaryHeaderVersionEXT - vendorID*: uint32 - deviceID*: uint32 - driverVersion*: uint32 - pipelineCacheUUID*: array[VK_UUID_SIZE, uint8] - applicationNameOffset*: uint32 - applicationVersion*: uint32 - engineNameOffset*: uint32 - VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - pipelineLibraryGroupHandles*: VkBool32 - VkDecompressMemoryRegionNV* = object - srcAddress*: VkDeviceAddress - dstAddress*: VkDeviceAddress - compressedSize*: VkDeviceSize - decompressedSize*: VkDeviceSize - decompressionMethod*: VkMemoryDecompressionMethodFlagsNV - VkPhysicalDeviceShaderCoreBuiltinsPropertiesARM* = object - sType*: VkStructureType - pNext*: pointer - shaderCoreMask*: uint64 - shaderCoreCount*: uint32 - shaderWarpsPerCore*: uint32 - VkPhysicalDeviceShaderCoreBuiltinsFeaturesARM* = object - sType*: VkStructureType - pNext*: pointer - shaderCoreBuiltins*: VkBool32 - VkSurfacePresentModeEXT* = object - sType*: VkStructureType - pNext*: pointer - presentMode*: VkPresentModeKHR - VkSurfacePresentScalingCapabilitiesEXT* = object - sType*: VkStructureType - pNext*: pointer - supportedPresentScaling*: VkPresentScalingFlagsEXT - supportedPresentGravityX*: VkPresentGravityFlagsEXT - supportedPresentGravityY*: VkPresentGravityFlagsEXT - minScaledImageExtent*: VkExtent2D - maxScaledImageExtent*: VkExtent2D - VkSurfacePresentModeCompatibilityEXT* = object - sType*: VkStructureType - pNext*: pointer - presentModeCount*: uint32 - pPresentModes*: ptr VkPresentModeKHR - VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT* = object - sType*: VkStructureType - pNext*: pointer - swapchainMaintenance1*: VkBool32 - VkSwapchainPresentFenceInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - swapchainCount*: uint32 - pFences*: ptr VkFence - VkSwapchainPresentModesCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - presentModeCount*: uint32 - pPresentModes*: ptr VkPresentModeKHR - VkSwapchainPresentModeInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - swapchainCount*: uint32 - pPresentModes*: ptr VkPresentModeKHR - VkSwapchainPresentScalingCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - scalingBehavior*: VkPresentScalingFlagsEXT - presentGravityX*: VkPresentGravityFlagsEXT - presentGravityY*: VkPresentGravityFlagsEXT - VkReleaseSwapchainImagesInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - swapchain*: VkSwapchainKHR - imageIndexCount*: uint32 - pImageIndices*: ptr uint32 - VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - rayTracingInvocationReorder*: VkBool32 - VkPhysicalDeviceRayTracingInvocationReorderPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - rayTracingInvocationReorderReorderingHint*: VkRayTracingInvocationReorderModeNV - VkDirectDriverLoadingInfoLUNARG* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDirectDriverLoadingFlagsLUNARG - pfnGetInstanceProcAddr*: PFN_vkGetInstanceProcAddrLUNARG - VkDirectDriverLoadingListLUNARG* = object - sType*: VkStructureType - pNext*: pointer - mode*: VkDirectDriverLoadingModeLUNARG - driverCount*: uint32 - pDrivers*: ptr VkDirectDriverLoadingInfoLUNARG - VkPhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM* = object - sType*: VkStructureType - pNext*: pointer - multiviewPerViewViewports*: VkBool32 - VkPhysicalDeviceShaderCorePropertiesARM* = object - sType*: VkStructureType - pNext*: pointer - pixelRate*: uint32 - texelRate*: uint32 - fmaRate*: uint32 - VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM* = object - sType*: VkStructureType - pNext*: pointer - multiviewPerViewRenderAreas*: VkBool32 - VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM* = object - sType*: VkStructureType - pNext*: pointer - perViewRenderAreaCount*: uint32 - pPerViewRenderAreas*: ptr VkRect2D -# feature VK_VERSION_1_0 -var - vkCreateInstance*: proc(pCreateInfo: ptr VkInstanceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pInstance: ptr VkInstance): VkResult {.stdcall.} - vkDestroyInstance*: proc(instance: VkInstance, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkEnumeratePhysicalDevices*: proc(instance: VkInstance, pPhysicalDeviceCount: ptr uint32, pPhysicalDevices: ptr VkPhysicalDevice): VkResult {.stdcall.} - vkGetPhysicalDeviceFeatures*: proc(physicalDevice: VkPhysicalDevice, pFeatures: ptr VkPhysicalDeviceFeatures): void {.stdcall.} - vkGetPhysicalDeviceFormatProperties*: proc(physicalDevice: VkPhysicalDevice, format: VkFormat, pFormatProperties: ptr VkFormatProperties): void {.stdcall.} - vkGetPhysicalDeviceImageFormatProperties*: proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, tiling: VkImageTiling, usage: VkImageUsageFlags, flags: VkImageCreateFlags, pImageFormatProperties: ptr VkImageFormatProperties): VkResult {.stdcall.} - vkGetPhysicalDeviceProperties*: proc(physicalDevice: VkPhysicalDevice, pProperties: ptr VkPhysicalDeviceProperties): void {.stdcall.} - vkGetPhysicalDeviceQueueFamilyProperties*: proc(physicalDevice: VkPhysicalDevice, pQueueFamilyPropertyCount: ptr uint32, pQueueFamilyProperties: ptr VkQueueFamilyProperties): void {.stdcall.} - vkGetPhysicalDeviceMemoryProperties*: proc(physicalDevice: VkPhysicalDevice, pMemoryProperties: ptr VkPhysicalDeviceMemoryProperties): void {.stdcall.} - vkGetDeviceProcAddr*: proc(device: VkDevice, pName: cstring): PFN_vkVoidFunction {.stdcall.} - vkCreateDevice*: proc(physicalDevice: VkPhysicalDevice, pCreateInfo: ptr VkDeviceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDevice: ptr VkDevice): VkResult {.stdcall.} - vkDestroyDevice*: proc(device: VkDevice, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkEnumerateInstanceExtensionProperties*: proc(pLayerName: cstring, pPropertyCount: ptr uint32, pProperties: ptr VkExtensionProperties): VkResult {.stdcall.} - vkEnumerateDeviceExtensionProperties*: proc(physicalDevice: VkPhysicalDevice, pLayerName: cstring, pPropertyCount: ptr uint32, pProperties: ptr VkExtensionProperties): VkResult {.stdcall.} - vkEnumerateInstanceLayerProperties*: proc(pPropertyCount: ptr uint32, pProperties: ptr VkLayerProperties): VkResult {.stdcall.} - vkEnumerateDeviceLayerProperties*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkLayerProperties): VkResult {.stdcall.} - vkGetDeviceQueue*: proc(device: VkDevice, queueFamilyIndex: uint32, queueIndex: uint32, pQueue: ptr VkQueue): void {.stdcall.} - vkQueueSubmit*: proc(queue: VkQueue, submitCount: uint32, pSubmits: ptr VkSubmitInfo, fence: VkFence): VkResult {.stdcall.} - vkQueueWaitIdle*: proc(queue: VkQueue): VkResult {.stdcall.} - vkDeviceWaitIdle*: proc(device: VkDevice): VkResult {.stdcall.} - vkAllocateMemory*: proc(device: VkDevice, pAllocateInfo: ptr VkMemoryAllocateInfo, pAllocator: ptr VkAllocationCallbacks, pMemory: ptr VkDeviceMemory): VkResult {.stdcall.} - vkFreeMemory*: proc(device: VkDevice, memory: VkDeviceMemory, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkMapMemory*: proc(device: VkDevice, memory: VkDeviceMemory, offset: VkDeviceSize, size: VkDeviceSize, flags: VkMemoryMapFlags, ppData: ptr pointer): VkResult {.stdcall.} - vkUnmapMemory*: proc(device: VkDevice, memory: VkDeviceMemory): void {.stdcall.} - vkFlushMappedMemoryRanges*: proc(device: VkDevice, memoryRangeCount: uint32, pMemoryRanges: ptr VkMappedMemoryRange): VkResult {.stdcall.} - vkInvalidateMappedMemoryRanges*: proc(device: VkDevice, memoryRangeCount: uint32, pMemoryRanges: ptr VkMappedMemoryRange): VkResult {.stdcall.} - vkGetDeviceMemoryCommitment*: proc(device: VkDevice, memory: VkDeviceMemory, pCommittedMemoryInBytes: ptr VkDeviceSize): void {.stdcall.} - vkBindBufferMemory*: proc(device: VkDevice, buffer: VkBuffer, memory: VkDeviceMemory, memoryOffset: VkDeviceSize): VkResult {.stdcall.} - vkBindImageMemory*: proc(device: VkDevice, image: VkImage, memory: VkDeviceMemory, memoryOffset: VkDeviceSize): VkResult {.stdcall.} - vkGetBufferMemoryRequirements*: proc(device: VkDevice, buffer: VkBuffer, pMemoryRequirements: ptr VkMemoryRequirements): void {.stdcall.} - vkGetImageMemoryRequirements*: proc(device: VkDevice, image: VkImage, pMemoryRequirements: ptr VkMemoryRequirements): void {.stdcall.} - vkGetImageSparseMemoryRequirements*: proc(device: VkDevice, image: VkImage, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements): void {.stdcall.} - vkGetPhysicalDeviceSparseImageFormatProperties*: proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, samples: VkSampleCountFlagBits, usage: VkImageUsageFlags, tiling: VkImageTiling, pPropertyCount: ptr uint32, pProperties: ptr VkSparseImageFormatProperties): void {.stdcall.} - vkQueueBindSparse*: proc(queue: VkQueue, bindInfoCount: uint32, pBindInfo: ptr VkBindSparseInfo, fence: VkFence): VkResult {.stdcall.} - vkCreateFence*: proc(device: VkDevice, pCreateInfo: ptr VkFenceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.} - vkDestroyFence*: proc(device: VkDevice, fence: VkFence, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkResetFences*: proc(device: VkDevice, fenceCount: uint32, pFences: ptr VkFence): VkResult {.stdcall.} - vkGetFenceStatus*: proc(device: VkDevice, fence: VkFence): VkResult {.stdcall.} - vkWaitForFences*: proc(device: VkDevice, fenceCount: uint32, pFences: ptr VkFence, waitAll: VkBool32, timeout: uint64): VkResult {.stdcall.} - vkCreateSemaphore*: proc(device: VkDevice, pCreateInfo: ptr VkSemaphoreCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSemaphore: ptr VkSemaphore): VkResult {.stdcall.} - vkDestroySemaphore*: proc(device: VkDevice, semaphore: VkSemaphore, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreateEvent*: proc(device: VkDevice, pCreateInfo: ptr VkEventCreateInfo, pAllocator: ptr VkAllocationCallbacks, pEvent: ptr VkEvent): VkResult {.stdcall.} - vkDestroyEvent*: proc(device: VkDevice, event: VkEvent, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetEventStatus*: proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.} - vkSetEvent*: proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.} - vkResetEvent*: proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.} - vkCreateQueryPool*: proc(device: VkDevice, pCreateInfo: ptr VkQueryPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pQueryPool: ptr VkQueryPool): VkResult {.stdcall.} - vkDestroyQueryPool*: proc(device: VkDevice, queryPool: VkQueryPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetQueryPoolResults*: proc(device: VkDevice, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32, dataSize: csize_t, pData: pointer, stride: VkDeviceSize, flags: VkQueryResultFlags): VkResult {.stdcall.} - vkCreateBuffer*: proc(device: VkDevice, pCreateInfo: ptr VkBufferCreateInfo, pAllocator: ptr VkAllocationCallbacks, pBuffer: ptr VkBuffer): VkResult {.stdcall.} - vkDestroyBuffer*: proc(device: VkDevice, buffer: VkBuffer, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreateBufferView*: proc(device: VkDevice, pCreateInfo: ptr VkBufferViewCreateInfo, pAllocator: ptr VkAllocationCallbacks, pView: ptr VkBufferView): VkResult {.stdcall.} - vkDestroyBufferView*: proc(device: VkDevice, bufferView: VkBufferView, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreateImage*: proc(device: VkDevice, pCreateInfo: ptr VkImageCreateInfo, pAllocator: ptr VkAllocationCallbacks, pImage: ptr VkImage): VkResult {.stdcall.} - vkDestroyImage*: proc(device: VkDevice, image: VkImage, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetImageSubresourceLayout*: proc(device: VkDevice, image: VkImage, pSubresource: ptr VkImageSubresource, pLayout: ptr VkSubresourceLayout): void {.stdcall.} - vkCreateImageView*: proc(device: VkDevice, pCreateInfo: ptr VkImageViewCreateInfo, pAllocator: ptr VkAllocationCallbacks, pView: ptr VkImageView): VkResult {.stdcall.} - vkDestroyImageView*: proc(device: VkDevice, imageView: VkImageView, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreateShaderModule*: proc(device: VkDevice, pCreateInfo: ptr VkShaderModuleCreateInfo, pAllocator: ptr VkAllocationCallbacks, pShaderModule: ptr VkShaderModule): VkResult {.stdcall.} - vkDestroyShaderModule*: proc(device: VkDevice, shaderModule: VkShaderModule, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreatePipelineCache*: proc(device: VkDevice, pCreateInfo: ptr VkPipelineCacheCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelineCache: ptr VkPipelineCache): VkResult {.stdcall.} - vkDestroyPipelineCache*: proc(device: VkDevice, pipelineCache: VkPipelineCache, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetPipelineCacheData*: proc(device: VkDevice, pipelineCache: VkPipelineCache, pDataSize: ptr csize_t, pData: pointer): VkResult {.stdcall.} - vkMergePipelineCaches*: proc(device: VkDevice, dstCache: VkPipelineCache, srcCacheCount: uint32, pSrcCaches: ptr VkPipelineCache): VkResult {.stdcall.} - vkCreateGraphicsPipelines*: proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkGraphicsPipelineCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.} - vkCreateComputePipelines*: proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkComputePipelineCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.} - vkDestroyPipeline*: proc(device: VkDevice, pipeline: VkPipeline, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreatePipelineLayout*: proc(device: VkDevice, pCreateInfo: ptr VkPipelineLayoutCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelineLayout: ptr VkPipelineLayout): VkResult {.stdcall.} - vkDestroyPipelineLayout*: proc(device: VkDevice, pipelineLayout: VkPipelineLayout, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreateSampler*: proc(device: VkDevice, pCreateInfo: ptr VkSamplerCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSampler: ptr VkSampler): VkResult {.stdcall.} - vkDestroySampler*: proc(device: VkDevice, sampler: VkSampler, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreateDescriptorSetLayout*: proc(device: VkDevice, pCreateInfo: ptr VkDescriptorSetLayoutCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSetLayout: ptr VkDescriptorSetLayout): VkResult {.stdcall.} - vkDestroyDescriptorSetLayout*: proc(device: VkDevice, descriptorSetLayout: VkDescriptorSetLayout, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreateDescriptorPool*: proc(device: VkDevice, pCreateInfo: ptr VkDescriptorPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDescriptorPool: ptr VkDescriptorPool): VkResult {.stdcall.} - vkDestroyDescriptorPool*: proc(device: VkDevice, descriptorPool: VkDescriptorPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkResetDescriptorPool*: proc(device: VkDevice, descriptorPool: VkDescriptorPool, flags: VkDescriptorPoolResetFlags): VkResult {.stdcall.} - vkAllocateDescriptorSets*: proc(device: VkDevice, pAllocateInfo: ptr VkDescriptorSetAllocateInfo, pDescriptorSets: ptr VkDescriptorSet): VkResult {.stdcall.} - vkFreeDescriptorSets*: proc(device: VkDevice, descriptorPool: VkDescriptorPool, descriptorSetCount: uint32, pDescriptorSets: ptr VkDescriptorSet): VkResult {.stdcall.} - vkUpdateDescriptorSets*: proc(device: VkDevice, descriptorWriteCount: uint32, pDescriptorWrites: ptr VkWriteDescriptorSet, descriptorCopyCount: uint32, pDescriptorCopies: ptr VkCopyDescriptorSet): void {.stdcall.} - vkCreateFramebuffer*: proc(device: VkDevice, pCreateInfo: ptr VkFramebufferCreateInfo, pAllocator: ptr VkAllocationCallbacks, pFramebuffer: ptr VkFramebuffer): VkResult {.stdcall.} - vkDestroyFramebuffer*: proc(device: VkDevice, framebuffer: VkFramebuffer, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreateRenderPass*: proc(device: VkDevice, pCreateInfo: ptr VkRenderPassCreateInfo, pAllocator: ptr VkAllocationCallbacks, pRenderPass: ptr VkRenderPass): VkResult {.stdcall.} - vkDestroyRenderPass*: proc(device: VkDevice, renderPass: VkRenderPass, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetRenderAreaGranularity*: proc(device: VkDevice, renderPass: VkRenderPass, pGranularity: ptr VkExtent2D): void {.stdcall.} - vkCreateCommandPool*: proc(device: VkDevice, pCreateInfo: ptr VkCommandPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pCommandPool: ptr VkCommandPool): VkResult {.stdcall.} - vkDestroyCommandPool*: proc(device: VkDevice, commandPool: VkCommandPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkResetCommandPool*: proc(device: VkDevice, commandPool: VkCommandPool, flags: VkCommandPoolResetFlags): VkResult {.stdcall.} - vkAllocateCommandBuffers*: proc(device: VkDevice, pAllocateInfo: ptr VkCommandBufferAllocateInfo, pCommandBuffers: ptr VkCommandBuffer): VkResult {.stdcall.} - vkFreeCommandBuffers*: proc(device: VkDevice, commandPool: VkCommandPool, commandBufferCount: uint32, pCommandBuffers: ptr VkCommandBuffer): void {.stdcall.} - vkBeginCommandBuffer*: proc(commandBuffer: VkCommandBuffer, pBeginInfo: ptr VkCommandBufferBeginInfo): VkResult {.stdcall.} - vkEndCommandBuffer*: proc(commandBuffer: VkCommandBuffer): VkResult {.stdcall.} - vkResetCommandBuffer*: proc(commandBuffer: VkCommandBuffer, flags: VkCommandBufferResetFlags): VkResult {.stdcall.} - vkCmdBindPipeline*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, pipeline: VkPipeline): void {.stdcall.} - vkCmdSetViewport*: proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewports: ptr VkViewport): void {.stdcall.} - vkCmdSetScissor*: proc(commandBuffer: VkCommandBuffer, firstScissor: uint32, scissorCount: uint32, pScissors: ptr VkRect2D): void {.stdcall.} - vkCmdSetLineWidth*: proc(commandBuffer: VkCommandBuffer, lineWidth: float32): void {.stdcall.} - vkCmdSetDepthBias*: proc(commandBuffer: VkCommandBuffer, depthBiasConstantFactor: float32, depthBiasClamp: float32, depthBiasSlopeFactor: float32): void {.stdcall.} - vkCmdSetBlendConstants*: proc(commandBuffer: VkCommandBuffer, blendConstants: array[4, float32]): void {.stdcall.} - vkCmdSetDepthBounds*: proc(commandBuffer: VkCommandBuffer, minDepthBounds: float32, maxDepthBounds: float32): void {.stdcall.} - vkCmdSetStencilCompareMask*: proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, compareMask: uint32): void {.stdcall.} - vkCmdSetStencilWriteMask*: proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, writeMask: uint32): void {.stdcall.} - vkCmdSetStencilReference*: proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, reference: uint32): void {.stdcall.} - vkCmdBindDescriptorSets*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, firstSet: uint32, descriptorSetCount: uint32, pDescriptorSets: ptr VkDescriptorSet, dynamicOffsetCount: uint32, pDynamicOffsets: ptr uint32): void {.stdcall.} - vkCmdBindIndexBuffer*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, indexType: VkIndexType): void {.stdcall.} - vkCmdBindVertexBuffers*: proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize): void {.stdcall.} - vkCmdDraw*: proc(commandBuffer: VkCommandBuffer, vertexCount: uint32, instanceCount: uint32, firstVertex: uint32, firstInstance: uint32): void {.stdcall.} - vkCmdDrawIndexed*: proc(commandBuffer: VkCommandBuffer, indexCount: uint32, instanceCount: uint32, firstIndex: uint32, vertexOffset: int32, firstInstance: uint32): void {.stdcall.} - vkCmdDrawIndirect*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.} - vkCmdDrawIndexedIndirect*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.} - vkCmdDispatch*: proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.} - vkCmdDispatchIndirect*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize): void {.stdcall.} - vkCmdCopyBuffer*: proc(commandBuffer: VkCommandBuffer, srcBuffer: VkBuffer, dstBuffer: VkBuffer, regionCount: uint32, pRegions: ptr VkBufferCopy): void {.stdcall.} - vkCmdCopyImage*: proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageCopy): void {.stdcall.} - vkCmdBlitImage*: proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageBlit, filter: VkFilter): void {.stdcall.} - vkCmdCopyBufferToImage*: proc(commandBuffer: VkCommandBuffer, srcBuffer: VkBuffer, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkBufferImageCopy): void {.stdcall.} - vkCmdCopyImageToBuffer*: proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstBuffer: VkBuffer, regionCount: uint32, pRegions: ptr VkBufferImageCopy): void {.stdcall.} - vkCmdUpdateBuffer*: proc(commandBuffer: VkCommandBuffer, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, dataSize: VkDeviceSize, pData: pointer): void {.stdcall.} - vkCmdFillBuffer*: proc(commandBuffer: VkCommandBuffer, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, size: VkDeviceSize, data: uint32): void {.stdcall.} - vkCmdClearColorImage*: proc(commandBuffer: VkCommandBuffer, image: VkImage, imageLayout: VkImageLayout, pColor: ptr VkClearColorValue, rangeCount: uint32, pRanges: ptr VkImageSubresourceRange): void {.stdcall.} - vkCmdClearDepthStencilImage*: proc(commandBuffer: VkCommandBuffer, image: VkImage, imageLayout: VkImageLayout, pDepthStencil: ptr VkClearDepthStencilValue, rangeCount: uint32, pRanges: ptr VkImageSubresourceRange): void {.stdcall.} - vkCmdClearAttachments*: proc(commandBuffer: VkCommandBuffer, attachmentCount: uint32, pAttachments: ptr VkClearAttachment, rectCount: uint32, pRects: ptr VkClearRect): void {.stdcall.} - vkCmdResolveImage*: proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageResolve): void {.stdcall.} - vkCmdSetEvent*: proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags): void {.stdcall.} - vkCmdResetEvent*: proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags): void {.stdcall.} - vkCmdWaitEvents*: proc(commandBuffer: VkCommandBuffer, eventCount: uint32, pEvents: ptr VkEvent, srcStageMask: VkPipelineStageFlags, dstStageMask: VkPipelineStageFlags, memoryBarrierCount: uint32, pMemoryBarriers: ptr VkMemoryBarrier, bufferMemoryBarrierCount: uint32, pBufferMemoryBarriers: ptr VkBufferMemoryBarrier, imageMemoryBarrierCount: uint32, pImageMemoryBarriers: ptr VkImageMemoryBarrier): void {.stdcall.} - vkCmdPipelineBarrier*: proc(commandBuffer: VkCommandBuffer, srcStageMask: VkPipelineStageFlags, dstStageMask: VkPipelineStageFlags, dependencyFlags: VkDependencyFlags, memoryBarrierCount: uint32, pMemoryBarriers: ptr VkMemoryBarrier, bufferMemoryBarrierCount: uint32, pBufferMemoryBarriers: ptr VkBufferMemoryBarrier, imageMemoryBarrierCount: uint32, pImageMemoryBarriers: ptr VkImageMemoryBarrier): void {.stdcall.} - vkCmdBeginQuery*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, flags: VkQueryControlFlags): void {.stdcall.} - vkCmdEndQuery*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32): void {.stdcall.} - vkCmdResetQueryPool*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32): void {.stdcall.} - vkCmdWriteTimestamp*: proc(commandBuffer: VkCommandBuffer, pipelineStage: VkPipelineStageFlagBits, queryPool: VkQueryPool, query: uint32): void {.stdcall.} - vkCmdCopyQueryPoolResults*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, stride: VkDeviceSize, flags: VkQueryResultFlags): void {.stdcall.} - vkCmdPushConstants*: proc(commandBuffer: VkCommandBuffer, layout: VkPipelineLayout, stageFlags: VkShaderStageFlags, offset: uint32, size: uint32, pValues: pointer): void {.stdcall.} - vkCmdBeginRenderPass*: proc(commandBuffer: VkCommandBuffer, pRenderPassBegin: ptr VkRenderPassBeginInfo, contents: VkSubpassContents): void {.stdcall.} - vkCmdNextSubpass*: proc(commandBuffer: VkCommandBuffer, contents: VkSubpassContents): void {.stdcall.} - vkCmdEndRenderPass*: proc(commandBuffer: VkCommandBuffer): void {.stdcall.} - vkCmdExecuteCommands*: proc(commandBuffer: VkCommandBuffer, commandBufferCount: uint32, pCommandBuffers: ptr VkCommandBuffer): void {.stdcall.} -proc loadVK_VERSION_1_0*(instance: VkInstance) = - vkDestroyInstance = cast[proc(instance: VkInstance, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyInstance")) - vkEnumeratePhysicalDevices = cast[proc(instance: VkInstance, pPhysicalDeviceCount: ptr uint32, pPhysicalDevices: ptr VkPhysicalDevice): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices")) - vkGetPhysicalDeviceFeatures = cast[proc(physicalDevice: VkPhysicalDevice, pFeatures: ptr VkPhysicalDeviceFeatures): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures")) - vkGetPhysicalDeviceFormatProperties = cast[proc(physicalDevice: VkPhysicalDevice, format: VkFormat, pFormatProperties: ptr VkFormatProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties")) - vkGetPhysicalDeviceImageFormatProperties = cast[proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, tiling: VkImageTiling, usage: VkImageUsageFlags, flags: VkImageCreateFlags, pImageFormatProperties: ptr VkImageFormatProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties")) - vkGetPhysicalDeviceProperties = cast[proc(physicalDevice: VkPhysicalDevice, pProperties: ptr VkPhysicalDeviceProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties")) - vkGetPhysicalDeviceQueueFamilyProperties = cast[proc(physicalDevice: VkPhysicalDevice, pQueueFamilyPropertyCount: ptr uint32, pQueueFamilyProperties: ptr VkQueueFamilyProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties")) - vkGetPhysicalDeviceMemoryProperties = cast[proc(physicalDevice: VkPhysicalDevice, pMemoryProperties: ptr VkPhysicalDeviceMemoryProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties")) - vkGetDeviceProcAddr = cast[proc(device: VkDevice, pName: cstring): PFN_vkVoidFunction {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceProcAddr")) - vkCreateDevice = cast[proc(physicalDevice: VkPhysicalDevice, pCreateInfo: ptr VkDeviceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDevice: ptr VkDevice): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDevice")) - vkDestroyDevice = cast[proc(device: VkDevice, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDevice")) - vkEnumerateDeviceExtensionProperties = cast[proc(physicalDevice: VkPhysicalDevice, pLayerName: cstring, pPropertyCount: ptr uint32, pProperties: ptr VkExtensionProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumerateDeviceExtensionProperties")) - vkEnumerateDeviceLayerProperties = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkLayerProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumerateDeviceLayerProperties")) - vkGetDeviceQueue = cast[proc(device: VkDevice, queueFamilyIndex: uint32, queueIndex: uint32, pQueue: ptr VkQueue): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceQueue")) - vkQueueSubmit = cast[proc(queue: VkQueue, submitCount: uint32, pSubmits: ptr VkSubmitInfo, fence: VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueSubmit")) - vkQueueWaitIdle = cast[proc(queue: VkQueue): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueWaitIdle")) - vkDeviceWaitIdle = cast[proc(device: VkDevice): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDeviceWaitIdle")) - vkAllocateMemory = cast[proc(device: VkDevice, pAllocateInfo: ptr VkMemoryAllocateInfo, pAllocator: ptr VkAllocationCallbacks, pMemory: ptr VkDeviceMemory): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAllocateMemory")) - vkFreeMemory = cast[proc(device: VkDevice, memory: VkDeviceMemory, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkFreeMemory")) - vkMapMemory = cast[proc(device: VkDevice, memory: VkDeviceMemory, offset: VkDeviceSize, size: VkDeviceSize, flags: VkMemoryMapFlags, ppData: ptr pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkMapMemory")) - vkUnmapMemory = cast[proc(device: VkDevice, memory: VkDeviceMemory): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkUnmapMemory")) - vkFlushMappedMemoryRanges = cast[proc(device: VkDevice, memoryRangeCount: uint32, pMemoryRanges: ptr VkMappedMemoryRange): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkFlushMappedMemoryRanges")) - vkInvalidateMappedMemoryRanges = cast[proc(device: VkDevice, memoryRangeCount: uint32, pMemoryRanges: ptr VkMappedMemoryRange): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkInvalidateMappedMemoryRanges")) - vkGetDeviceMemoryCommitment = cast[proc(device: VkDevice, memory: VkDeviceMemory, pCommittedMemoryInBytes: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceMemoryCommitment")) - vkBindBufferMemory = cast[proc(device: VkDevice, buffer: VkBuffer, memory: VkDeviceMemory, memoryOffset: VkDeviceSize): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindBufferMemory")) - vkBindImageMemory = cast[proc(device: VkDevice, image: VkImage, memory: VkDeviceMemory, memoryOffset: VkDeviceSize): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindImageMemory")) - vkGetBufferMemoryRequirements = cast[proc(device: VkDevice, buffer: VkBuffer, pMemoryRequirements: ptr VkMemoryRequirements): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferMemoryRequirements")) - vkGetImageMemoryRequirements = cast[proc(device: VkDevice, image: VkImage, pMemoryRequirements: ptr VkMemoryRequirements): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageMemoryRequirements")) - vkGetImageSparseMemoryRequirements = cast[proc(device: VkDevice, image: VkImage, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageSparseMemoryRequirements")) - vkGetPhysicalDeviceSparseImageFormatProperties = cast[proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, samples: VkSampleCountFlagBits, usage: VkImageUsageFlags, tiling: VkImageTiling, pPropertyCount: ptr uint32, pProperties: ptr VkSparseImageFormatProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties")) - vkQueueBindSparse = cast[proc(queue: VkQueue, bindInfoCount: uint32, pBindInfo: ptr VkBindSparseInfo, fence: VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueBindSparse")) - vkCreateFence = cast[proc(device: VkDevice, pCreateInfo: ptr VkFenceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateFence")) - vkDestroyFence = cast[proc(device: VkDevice, fence: VkFence, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyFence")) - vkResetFences = cast[proc(device: VkDevice, fenceCount: uint32, pFences: ptr VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetFences")) - vkGetFenceStatus = cast[proc(device: VkDevice, fence: VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetFenceStatus")) - vkWaitForFences = cast[proc(device: VkDevice, fenceCount: uint32, pFences: ptr VkFence, waitAll: VkBool32, timeout: uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkWaitForFences")) - vkCreateSemaphore = cast[proc(device: VkDevice, pCreateInfo: ptr VkSemaphoreCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSemaphore: ptr VkSemaphore): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateSemaphore")) - vkDestroySemaphore = cast[proc(device: VkDevice, semaphore: VkSemaphore, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroySemaphore")) - vkCreateEvent = cast[proc(device: VkDevice, pCreateInfo: ptr VkEventCreateInfo, pAllocator: ptr VkAllocationCallbacks, pEvent: ptr VkEvent): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateEvent")) - vkDestroyEvent = cast[proc(device: VkDevice, event: VkEvent, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyEvent")) - vkGetEventStatus = cast[proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetEventStatus")) - vkSetEvent = cast[proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetEvent")) - vkResetEvent = cast[proc(device: VkDevice, event: VkEvent): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetEvent")) - vkCreateQueryPool = cast[proc(device: VkDevice, pCreateInfo: ptr VkQueryPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pQueryPool: ptr VkQueryPool): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateQueryPool")) - vkDestroyQueryPool = cast[proc(device: VkDevice, queryPool: VkQueryPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyQueryPool")) - vkGetQueryPoolResults = cast[proc(device: VkDevice, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32, dataSize: csize_t, pData: pointer, stride: VkDeviceSize, flags: VkQueryResultFlags): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetQueryPoolResults")) - vkCreateBuffer = cast[proc(device: VkDevice, pCreateInfo: ptr VkBufferCreateInfo, pAllocator: ptr VkAllocationCallbacks, pBuffer: ptr VkBuffer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateBuffer")) - vkDestroyBuffer = cast[proc(device: VkDevice, buffer: VkBuffer, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyBuffer")) - vkCreateBufferView = cast[proc(device: VkDevice, pCreateInfo: ptr VkBufferViewCreateInfo, pAllocator: ptr VkAllocationCallbacks, pView: ptr VkBufferView): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateBufferView")) - vkDestroyBufferView = cast[proc(device: VkDevice, bufferView: VkBufferView, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyBufferView")) - vkCreateImage = cast[proc(device: VkDevice, pCreateInfo: ptr VkImageCreateInfo, pAllocator: ptr VkAllocationCallbacks, pImage: ptr VkImage): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateImage")) - vkDestroyImage = cast[proc(device: VkDevice, image: VkImage, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyImage")) - vkGetImageSubresourceLayout = cast[proc(device: VkDevice, image: VkImage, pSubresource: ptr VkImageSubresource, pLayout: ptr VkSubresourceLayout): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageSubresourceLayout")) - vkCreateImageView = cast[proc(device: VkDevice, pCreateInfo: ptr VkImageViewCreateInfo, pAllocator: ptr VkAllocationCallbacks, pView: ptr VkImageView): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateImageView")) - vkDestroyImageView = cast[proc(device: VkDevice, imageView: VkImageView, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyImageView")) - vkCreateShaderModule = cast[proc(device: VkDevice, pCreateInfo: ptr VkShaderModuleCreateInfo, pAllocator: ptr VkAllocationCallbacks, pShaderModule: ptr VkShaderModule): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateShaderModule")) - vkDestroyShaderModule = cast[proc(device: VkDevice, shaderModule: VkShaderModule, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyShaderModule")) - vkCreatePipelineCache = cast[proc(device: VkDevice, pCreateInfo: ptr VkPipelineCacheCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelineCache: ptr VkPipelineCache): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreatePipelineCache")) - vkDestroyPipelineCache = cast[proc(device: VkDevice, pipelineCache: VkPipelineCache, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyPipelineCache")) - vkGetPipelineCacheData = cast[proc(device: VkDevice, pipelineCache: VkPipelineCache, pDataSize: ptr csize_t, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPipelineCacheData")) - vkMergePipelineCaches = cast[proc(device: VkDevice, dstCache: VkPipelineCache, srcCacheCount: uint32, pSrcCaches: ptr VkPipelineCache): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkMergePipelineCaches")) - vkCreateGraphicsPipelines = cast[proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkGraphicsPipelineCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateGraphicsPipelines")) - vkCreateComputePipelines = cast[proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkComputePipelineCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateComputePipelines")) - vkDestroyPipeline = cast[proc(device: VkDevice, pipeline: VkPipeline, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyPipeline")) - vkCreatePipelineLayout = cast[proc(device: VkDevice, pCreateInfo: ptr VkPipelineLayoutCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPipelineLayout: ptr VkPipelineLayout): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreatePipelineLayout")) - vkDestroyPipelineLayout = cast[proc(device: VkDevice, pipelineLayout: VkPipelineLayout, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyPipelineLayout")) - vkCreateSampler = cast[proc(device: VkDevice, pCreateInfo: ptr VkSamplerCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSampler: ptr VkSampler): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateSampler")) - vkDestroySampler = cast[proc(device: VkDevice, sampler: VkSampler, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroySampler")) - vkCreateDescriptorSetLayout = cast[proc(device: VkDevice, pCreateInfo: ptr VkDescriptorSetLayoutCreateInfo, pAllocator: ptr VkAllocationCallbacks, pSetLayout: ptr VkDescriptorSetLayout): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDescriptorSetLayout")) - vkDestroyDescriptorSetLayout = cast[proc(device: VkDevice, descriptorSetLayout: VkDescriptorSetLayout, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDescriptorSetLayout")) - vkCreateDescriptorPool = cast[proc(device: VkDevice, pCreateInfo: ptr VkDescriptorPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDescriptorPool: ptr VkDescriptorPool): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDescriptorPool")) - vkDestroyDescriptorPool = cast[proc(device: VkDevice, descriptorPool: VkDescriptorPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDescriptorPool")) - vkResetDescriptorPool = cast[proc(device: VkDevice, descriptorPool: VkDescriptorPool, flags: VkDescriptorPoolResetFlags): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetDescriptorPool")) - vkAllocateDescriptorSets = cast[proc(device: VkDevice, pAllocateInfo: ptr VkDescriptorSetAllocateInfo, pDescriptorSets: ptr VkDescriptorSet): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAllocateDescriptorSets")) - vkFreeDescriptorSets = cast[proc(device: VkDevice, descriptorPool: VkDescriptorPool, descriptorSetCount: uint32, pDescriptorSets: ptr VkDescriptorSet): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkFreeDescriptorSets")) - vkUpdateDescriptorSets = cast[proc(device: VkDevice, descriptorWriteCount: uint32, pDescriptorWrites: ptr VkWriteDescriptorSet, descriptorCopyCount: uint32, pDescriptorCopies: ptr VkCopyDescriptorSet): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkUpdateDescriptorSets")) - vkCreateFramebuffer = cast[proc(device: VkDevice, pCreateInfo: ptr VkFramebufferCreateInfo, pAllocator: ptr VkAllocationCallbacks, pFramebuffer: ptr VkFramebuffer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateFramebuffer")) - vkDestroyFramebuffer = cast[proc(device: VkDevice, framebuffer: VkFramebuffer, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyFramebuffer")) - vkCreateRenderPass = cast[proc(device: VkDevice, pCreateInfo: ptr VkRenderPassCreateInfo, pAllocator: ptr VkAllocationCallbacks, pRenderPass: ptr VkRenderPass): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateRenderPass")) - vkDestroyRenderPass = cast[proc(device: VkDevice, renderPass: VkRenderPass, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyRenderPass")) - vkGetRenderAreaGranularity = cast[proc(device: VkDevice, renderPass: VkRenderPass, pGranularity: ptr VkExtent2D): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRenderAreaGranularity")) - vkCreateCommandPool = cast[proc(device: VkDevice, pCreateInfo: ptr VkCommandPoolCreateInfo, pAllocator: ptr VkAllocationCallbacks, pCommandPool: ptr VkCommandPool): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateCommandPool")) - vkDestroyCommandPool = cast[proc(device: VkDevice, commandPool: VkCommandPool, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyCommandPool")) - vkResetCommandPool = cast[proc(device: VkDevice, commandPool: VkCommandPool, flags: VkCommandPoolResetFlags): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetCommandPool")) - vkAllocateCommandBuffers = cast[proc(device: VkDevice, pAllocateInfo: ptr VkCommandBufferAllocateInfo, pCommandBuffers: ptr VkCommandBuffer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAllocateCommandBuffers")) - vkFreeCommandBuffers = cast[proc(device: VkDevice, commandPool: VkCommandPool, commandBufferCount: uint32, pCommandBuffers: ptr VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkFreeCommandBuffers")) - vkBeginCommandBuffer = cast[proc(commandBuffer: VkCommandBuffer, pBeginInfo: ptr VkCommandBufferBeginInfo): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBeginCommandBuffer")) - vkEndCommandBuffer = cast[proc(commandBuffer: VkCommandBuffer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEndCommandBuffer")) - vkResetCommandBuffer = cast[proc(commandBuffer: VkCommandBuffer, flags: VkCommandBufferResetFlags): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetCommandBuffer")) - vkCmdBindPipeline = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, pipeline: VkPipeline): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindPipeline")) - vkCmdSetViewport = cast[proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewports: ptr VkViewport): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewport")) - vkCmdSetScissor = cast[proc(commandBuffer: VkCommandBuffer, firstScissor: uint32, scissorCount: uint32, pScissors: ptr VkRect2D): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetScissor")) - vkCmdSetLineWidth = cast[proc(commandBuffer: VkCommandBuffer, lineWidth: float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetLineWidth")) - vkCmdSetDepthBias = cast[proc(commandBuffer: VkCommandBuffer, depthBiasConstantFactor: float32, depthBiasClamp: float32, depthBiasSlopeFactor: float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthBias")) - vkCmdSetBlendConstants = cast[proc(commandBuffer: VkCommandBuffer, blendConstants: array[4, float32]): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetBlendConstants")) - vkCmdSetDepthBounds = cast[proc(commandBuffer: VkCommandBuffer, minDepthBounds: float32, maxDepthBounds: float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthBounds")) - vkCmdSetStencilCompareMask = cast[proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, compareMask: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetStencilCompareMask")) - vkCmdSetStencilWriteMask = cast[proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, writeMask: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetStencilWriteMask")) - vkCmdSetStencilReference = cast[proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, reference: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetStencilReference")) - vkCmdBindDescriptorSets = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, firstSet: uint32, descriptorSetCount: uint32, pDescriptorSets: ptr VkDescriptorSet, dynamicOffsetCount: uint32, pDynamicOffsets: ptr uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindDescriptorSets")) - vkCmdBindIndexBuffer = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, indexType: VkIndexType): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindIndexBuffer")) - vkCmdBindVertexBuffers = cast[proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindVertexBuffers")) - vkCmdDraw = cast[proc(commandBuffer: VkCommandBuffer, vertexCount: uint32, instanceCount: uint32, firstVertex: uint32, firstInstance: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDraw")) - vkCmdDrawIndexed = cast[proc(commandBuffer: VkCommandBuffer, indexCount: uint32, instanceCount: uint32, firstIndex: uint32, vertexOffset: int32, firstInstance: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndexed")) - vkCmdDrawIndirect = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndirect")) - vkCmdDrawIndexedIndirect = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirect")) - vkCmdDispatch = cast[proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDispatch")) - vkCmdDispatchIndirect = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDispatchIndirect")) - vkCmdCopyBuffer = cast[proc(commandBuffer: VkCommandBuffer, srcBuffer: VkBuffer, dstBuffer: VkBuffer, regionCount: uint32, pRegions: ptr VkBufferCopy): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyBuffer")) - vkCmdCopyImage = cast[proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageCopy): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyImage")) - vkCmdBlitImage = cast[proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageBlit, filter: VkFilter): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBlitImage")) - vkCmdCopyBufferToImage = cast[proc(commandBuffer: VkCommandBuffer, srcBuffer: VkBuffer, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkBufferImageCopy): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyBufferToImage")) - vkCmdCopyImageToBuffer = cast[proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstBuffer: VkBuffer, regionCount: uint32, pRegions: ptr VkBufferImageCopy): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyImageToBuffer")) - vkCmdUpdateBuffer = cast[proc(commandBuffer: VkCommandBuffer, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, dataSize: VkDeviceSize, pData: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdUpdateBuffer")) - vkCmdFillBuffer = cast[proc(commandBuffer: VkCommandBuffer, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, size: VkDeviceSize, data: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdFillBuffer")) - vkCmdClearColorImage = cast[proc(commandBuffer: VkCommandBuffer, image: VkImage, imageLayout: VkImageLayout, pColor: ptr VkClearColorValue, rangeCount: uint32, pRanges: ptr VkImageSubresourceRange): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdClearColorImage")) - vkCmdClearDepthStencilImage = cast[proc(commandBuffer: VkCommandBuffer, image: VkImage, imageLayout: VkImageLayout, pDepthStencil: ptr VkClearDepthStencilValue, rangeCount: uint32, pRanges: ptr VkImageSubresourceRange): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdClearDepthStencilImage")) - vkCmdClearAttachments = cast[proc(commandBuffer: VkCommandBuffer, attachmentCount: uint32, pAttachments: ptr VkClearAttachment, rectCount: uint32, pRects: ptr VkClearRect): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdClearAttachments")) - vkCmdResolveImage = cast[proc(commandBuffer: VkCommandBuffer, srcImage: VkImage, srcImageLayout: VkImageLayout, dstImage: VkImage, dstImageLayout: VkImageLayout, regionCount: uint32, pRegions: ptr VkImageResolve): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdResolveImage")) - vkCmdSetEvent = cast[proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetEvent")) - vkCmdResetEvent = cast[proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdResetEvent")) - vkCmdWaitEvents = cast[proc(commandBuffer: VkCommandBuffer, eventCount: uint32, pEvents: ptr VkEvent, srcStageMask: VkPipelineStageFlags, dstStageMask: VkPipelineStageFlags, memoryBarrierCount: uint32, pMemoryBarriers: ptr VkMemoryBarrier, bufferMemoryBarrierCount: uint32, pBufferMemoryBarriers: ptr VkBufferMemoryBarrier, imageMemoryBarrierCount: uint32, pImageMemoryBarriers: ptr VkImageMemoryBarrier): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWaitEvents")) - vkCmdPipelineBarrier = cast[proc(commandBuffer: VkCommandBuffer, srcStageMask: VkPipelineStageFlags, dstStageMask: VkPipelineStageFlags, dependencyFlags: VkDependencyFlags, memoryBarrierCount: uint32, pMemoryBarriers: ptr VkMemoryBarrier, bufferMemoryBarrierCount: uint32, pBufferMemoryBarriers: ptr VkBufferMemoryBarrier, imageMemoryBarrierCount: uint32, pImageMemoryBarriers: ptr VkImageMemoryBarrier): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPipelineBarrier")) - vkCmdBeginQuery = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, flags: VkQueryControlFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginQuery")) - vkCmdEndQuery = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndQuery")) - vkCmdResetQueryPool = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdResetQueryPool")) - vkCmdWriteTimestamp = cast[proc(commandBuffer: VkCommandBuffer, pipelineStage: VkPipelineStageFlagBits, queryPool: VkQueryPool, query: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteTimestamp")) - vkCmdCopyQueryPoolResults = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, stride: VkDeviceSize, flags: VkQueryResultFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyQueryPoolResults")) - vkCmdPushConstants = cast[proc(commandBuffer: VkCommandBuffer, layout: VkPipelineLayout, stageFlags: VkShaderStageFlags, offset: uint32, size: uint32, pValues: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPushConstants")) - vkCmdBeginRenderPass = cast[proc(commandBuffer: VkCommandBuffer, pRenderPassBegin: ptr VkRenderPassBeginInfo, contents: VkSubpassContents): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginRenderPass")) - vkCmdNextSubpass = cast[proc(commandBuffer: VkCommandBuffer, contents: VkSubpassContents): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdNextSubpass")) - vkCmdEndRenderPass = cast[proc(commandBuffer: VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndRenderPass")) - vkCmdExecuteCommands = cast[proc(commandBuffer: VkCommandBuffer, commandBufferCount: uint32, pCommandBuffers: ptr VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdExecuteCommands")) - -# feature VK_VERSION_1_1 -var - vkEnumerateInstanceVersion*: proc(pApiVersion: ptr uint32): VkResult {.stdcall.} - vkBindBufferMemory2*: proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindBufferMemoryInfo): VkResult {.stdcall.} - vkBindImageMemory2*: proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindImageMemoryInfo): VkResult {.stdcall.} - vkGetDeviceGroupPeerMemoryFeatures*: proc(device: VkDevice, heapIndex: uint32, localDeviceIndex: uint32, remoteDeviceIndex: uint32, pPeerMemoryFeatures: ptr VkPeerMemoryFeatureFlags): void {.stdcall.} - vkCmdSetDeviceMask*: proc(commandBuffer: VkCommandBuffer, deviceMask: uint32): void {.stdcall.} - vkCmdDispatchBase*: proc(commandBuffer: VkCommandBuffer, baseGroupX: uint32, baseGroupY: uint32, baseGroupZ: uint32, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.} - vkEnumeratePhysicalDeviceGroups*: proc(instance: VkInstance, pPhysicalDeviceGroupCount: ptr uint32, pPhysicalDeviceGroupProperties: ptr VkPhysicalDeviceGroupProperties): VkResult {.stdcall.} - vkGetImageMemoryRequirements2*: proc(device: VkDevice, pInfo: ptr VkImageMemoryRequirementsInfo2, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.} - vkGetBufferMemoryRequirements2*: proc(device: VkDevice, pInfo: ptr VkBufferMemoryRequirementsInfo2, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.} - vkGetImageSparseMemoryRequirements2*: proc(device: VkDevice, pInfo: ptr VkImageSparseMemoryRequirementsInfo2, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements2): void {.stdcall.} - vkGetPhysicalDeviceFeatures2*: proc(physicalDevice: VkPhysicalDevice, pFeatures: ptr VkPhysicalDeviceFeatures2): void {.stdcall.} - vkGetPhysicalDeviceProperties2*: proc(physicalDevice: VkPhysicalDevice, pProperties: ptr VkPhysicalDeviceProperties2): void {.stdcall.} - vkGetPhysicalDeviceFormatProperties2*: proc(physicalDevice: VkPhysicalDevice, format: VkFormat, pFormatProperties: ptr VkFormatProperties2): void {.stdcall.} - vkGetPhysicalDeviceImageFormatProperties2*: proc(physicalDevice: VkPhysicalDevice, pImageFormatInfo: ptr VkPhysicalDeviceImageFormatInfo2, pImageFormatProperties: ptr VkImageFormatProperties2): VkResult {.stdcall.} - vkGetPhysicalDeviceQueueFamilyProperties2*: proc(physicalDevice: VkPhysicalDevice, pQueueFamilyPropertyCount: ptr uint32, pQueueFamilyProperties: ptr VkQueueFamilyProperties2): void {.stdcall.} - vkGetPhysicalDeviceMemoryProperties2*: proc(physicalDevice: VkPhysicalDevice, pMemoryProperties: ptr VkPhysicalDeviceMemoryProperties2): void {.stdcall.} - vkGetPhysicalDeviceSparseImageFormatProperties2*: proc(physicalDevice: VkPhysicalDevice, pFormatInfo: ptr VkPhysicalDeviceSparseImageFormatInfo2, pPropertyCount: ptr uint32, pProperties: ptr VkSparseImageFormatProperties2): void {.stdcall.} - vkTrimCommandPool*: proc(device: VkDevice, commandPool: VkCommandPool, flags: VkCommandPoolTrimFlags): void {.stdcall.} - vkGetDeviceQueue2*: proc(device: VkDevice, pQueueInfo: ptr VkDeviceQueueInfo2, pQueue: ptr VkQueue): void {.stdcall.} - vkCreateSamplerYcbcrConversion*: proc(device: VkDevice, pCreateInfo: ptr VkSamplerYcbcrConversionCreateInfo, pAllocator: ptr VkAllocationCallbacks, pYcbcrConversion: ptr VkSamplerYcbcrConversion): VkResult {.stdcall.} - vkDestroySamplerYcbcrConversion*: proc(device: VkDevice, ycbcrConversion: VkSamplerYcbcrConversion, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCreateDescriptorUpdateTemplate*: proc(device: VkDevice, pCreateInfo: ptr VkDescriptorUpdateTemplateCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDescriptorUpdateTemplate: ptr VkDescriptorUpdateTemplate): VkResult {.stdcall.} - vkDestroyDescriptorUpdateTemplate*: proc(device: VkDevice, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkUpdateDescriptorSetWithTemplate*: proc(device: VkDevice, descriptorSet: VkDescriptorSet, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, pData: pointer): void {.stdcall.} - vkGetPhysicalDeviceExternalBufferProperties*: proc(physicalDevice: VkPhysicalDevice, pExternalBufferInfo: ptr VkPhysicalDeviceExternalBufferInfo, pExternalBufferProperties: ptr VkExternalBufferProperties): void {.stdcall.} - vkGetPhysicalDeviceExternalFenceProperties*: proc(physicalDevice: VkPhysicalDevice, pExternalFenceInfo: ptr VkPhysicalDeviceExternalFenceInfo, pExternalFenceProperties: ptr VkExternalFenceProperties): void {.stdcall.} - vkGetPhysicalDeviceExternalSemaphoreProperties*: proc(physicalDevice: VkPhysicalDevice, pExternalSemaphoreInfo: ptr VkPhysicalDeviceExternalSemaphoreInfo, pExternalSemaphoreProperties: ptr VkExternalSemaphoreProperties): void {.stdcall.} - vkGetDescriptorSetLayoutSupport*: proc(device: VkDevice, pCreateInfo: ptr VkDescriptorSetLayoutCreateInfo, pSupport: ptr VkDescriptorSetLayoutSupport): void {.stdcall.} -proc loadVK_VERSION_1_1*(instance: VkInstance) = - vkBindBufferMemory2 = cast[proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindBufferMemoryInfo): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindBufferMemory2")) - vkBindImageMemory2 = cast[proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindImageMemoryInfo): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindImageMemory2")) - vkGetDeviceGroupPeerMemoryFeatures = cast[proc(device: VkDevice, heapIndex: uint32, localDeviceIndex: uint32, remoteDeviceIndex: uint32, pPeerMemoryFeatures: ptr VkPeerMemoryFeatureFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceGroupPeerMemoryFeatures")) - vkCmdSetDeviceMask = cast[proc(commandBuffer: VkCommandBuffer, deviceMask: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDeviceMask")) - vkCmdDispatchBase = cast[proc(commandBuffer: VkCommandBuffer, baseGroupX: uint32, baseGroupY: uint32, baseGroupZ: uint32, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDispatchBase")) - vkEnumeratePhysicalDeviceGroups = cast[proc(instance: VkInstance, pPhysicalDeviceGroupCount: ptr uint32, pPhysicalDeviceGroupProperties: ptr VkPhysicalDeviceGroupProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroups")) - vkGetImageMemoryRequirements2 = cast[proc(device: VkDevice, pInfo: ptr VkImageMemoryRequirementsInfo2, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageMemoryRequirements2")) - vkGetBufferMemoryRequirements2 = cast[proc(device: VkDevice, pInfo: ptr VkBufferMemoryRequirementsInfo2, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferMemoryRequirements2")) - vkGetImageSparseMemoryRequirements2 = cast[proc(device: VkDevice, pInfo: ptr VkImageSparseMemoryRequirementsInfo2, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageSparseMemoryRequirements2")) - vkGetPhysicalDeviceFeatures2 = cast[proc(physicalDevice: VkPhysicalDevice, pFeatures: ptr VkPhysicalDeviceFeatures2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2")) - vkGetPhysicalDeviceProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, pProperties: ptr VkPhysicalDeviceProperties2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2")) - vkGetPhysicalDeviceFormatProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, format: VkFormat, pFormatProperties: ptr VkFormatProperties2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2")) - vkGetPhysicalDeviceImageFormatProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, pImageFormatInfo: ptr VkPhysicalDeviceImageFormatInfo2, pImageFormatProperties: ptr VkImageFormatProperties2): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2")) - vkGetPhysicalDeviceQueueFamilyProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, pQueueFamilyPropertyCount: ptr uint32, pQueueFamilyProperties: ptr VkQueueFamilyProperties2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2")) - vkGetPhysicalDeviceMemoryProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, pMemoryProperties: ptr VkPhysicalDeviceMemoryProperties2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2")) - vkGetPhysicalDeviceSparseImageFormatProperties2 = cast[proc(physicalDevice: VkPhysicalDevice, pFormatInfo: ptr VkPhysicalDeviceSparseImageFormatInfo2, pPropertyCount: ptr uint32, pProperties: ptr VkSparseImageFormatProperties2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2")) - vkTrimCommandPool = cast[proc(device: VkDevice, commandPool: VkCommandPool, flags: VkCommandPoolTrimFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkTrimCommandPool")) - vkGetDeviceQueue2 = cast[proc(device: VkDevice, pQueueInfo: ptr VkDeviceQueueInfo2, pQueue: ptr VkQueue): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceQueue2")) - vkCreateSamplerYcbcrConversion = cast[proc(device: VkDevice, pCreateInfo: ptr VkSamplerYcbcrConversionCreateInfo, pAllocator: ptr VkAllocationCallbacks, pYcbcrConversion: ptr VkSamplerYcbcrConversion): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateSamplerYcbcrConversion")) - vkDestroySamplerYcbcrConversion = cast[proc(device: VkDevice, ycbcrConversion: VkSamplerYcbcrConversion, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroySamplerYcbcrConversion")) - vkCreateDescriptorUpdateTemplate = cast[proc(device: VkDevice, pCreateInfo: ptr VkDescriptorUpdateTemplateCreateInfo, pAllocator: ptr VkAllocationCallbacks, pDescriptorUpdateTemplate: ptr VkDescriptorUpdateTemplate): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDescriptorUpdateTemplate")) - vkDestroyDescriptorUpdateTemplate = cast[proc(device: VkDevice, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDescriptorUpdateTemplate")) - vkUpdateDescriptorSetWithTemplate = cast[proc(device: VkDevice, descriptorSet: VkDescriptorSet, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, pData: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkUpdateDescriptorSetWithTemplate")) - vkGetPhysicalDeviceExternalBufferProperties = cast[proc(physicalDevice: VkPhysicalDevice, pExternalBufferInfo: ptr VkPhysicalDeviceExternalBufferInfo, pExternalBufferProperties: ptr VkExternalBufferProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferProperties")) - vkGetPhysicalDeviceExternalFenceProperties = cast[proc(physicalDevice: VkPhysicalDevice, pExternalFenceInfo: ptr VkPhysicalDeviceExternalFenceInfo, pExternalFenceProperties: ptr VkExternalFenceProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFenceProperties")) - vkGetPhysicalDeviceExternalSemaphoreProperties = cast[proc(physicalDevice: VkPhysicalDevice, pExternalSemaphoreInfo: ptr VkPhysicalDeviceExternalSemaphoreInfo, pExternalSemaphoreProperties: ptr VkExternalSemaphoreProperties): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphoreProperties")) - vkGetDescriptorSetLayoutSupport = cast[proc(device: VkDevice, pCreateInfo: ptr VkDescriptorSetLayoutCreateInfo, pSupport: ptr VkDescriptorSetLayoutSupport): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorSetLayoutSupport")) - -# feature VK_VERSION_1_2 -var - vkCmdDrawIndirectCount*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.} - vkCmdDrawIndexedIndirectCount*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.} - vkCreateRenderPass2*: proc(device: VkDevice, pCreateInfo: ptr VkRenderPassCreateInfo2, pAllocator: ptr VkAllocationCallbacks, pRenderPass: ptr VkRenderPass): VkResult {.stdcall.} - vkCmdBeginRenderPass2*: proc(commandBuffer: VkCommandBuffer, pRenderPassBegin: ptr VkRenderPassBeginInfo, pSubpassBeginInfo: ptr VkSubpassBeginInfo): void {.stdcall.} - vkCmdNextSubpass2*: proc(commandBuffer: VkCommandBuffer, pSubpassBeginInfo: ptr VkSubpassBeginInfo, pSubpassEndInfo: ptr VkSubpassEndInfo): void {.stdcall.} - vkCmdEndRenderPass2*: proc(commandBuffer: VkCommandBuffer, pSubpassEndInfo: ptr VkSubpassEndInfo): void {.stdcall.} - vkResetQueryPool*: proc(device: VkDevice, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32): void {.stdcall.} - vkGetSemaphoreCounterValue*: proc(device: VkDevice, semaphore: VkSemaphore, pValue: ptr uint64): VkResult {.stdcall.} - vkWaitSemaphores*: proc(device: VkDevice, pWaitInfo: ptr VkSemaphoreWaitInfo, timeout: uint64): VkResult {.stdcall.} - vkSignalSemaphore*: proc(device: VkDevice, pSignalInfo: ptr VkSemaphoreSignalInfo): VkResult {.stdcall.} - vkGetBufferDeviceAddress*: proc(device: VkDevice, pInfo: ptr VkBufferDeviceAddressInfo): VkDeviceAddress {.stdcall.} - vkGetBufferOpaqueCaptureAddress*: proc(device: VkDevice, pInfo: ptr VkBufferDeviceAddressInfo): uint64 {.stdcall.} - vkGetDeviceMemoryOpaqueCaptureAddress*: proc(device: VkDevice, pInfo: ptr VkDeviceMemoryOpaqueCaptureAddressInfo): uint64 {.stdcall.} -proc loadVK_VERSION_1_2*(instance: VkInstance) = - vkCmdDrawIndirectCount = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndirectCount")) - vkCmdDrawIndexedIndirectCount = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirectCount")) - vkCreateRenderPass2 = cast[proc(device: VkDevice, pCreateInfo: ptr VkRenderPassCreateInfo2, pAllocator: ptr VkAllocationCallbacks, pRenderPass: ptr VkRenderPass): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateRenderPass2")) - vkCmdBeginRenderPass2 = cast[proc(commandBuffer: VkCommandBuffer, pRenderPassBegin: ptr VkRenderPassBeginInfo, pSubpassBeginInfo: ptr VkSubpassBeginInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginRenderPass2")) - vkCmdNextSubpass2 = cast[proc(commandBuffer: VkCommandBuffer, pSubpassBeginInfo: ptr VkSubpassBeginInfo, pSubpassEndInfo: ptr VkSubpassEndInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdNextSubpass2")) - vkCmdEndRenderPass2 = cast[proc(commandBuffer: VkCommandBuffer, pSubpassEndInfo: ptr VkSubpassEndInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndRenderPass2")) - vkResetQueryPool = cast[proc(device: VkDevice, queryPool: VkQueryPool, firstQuery: uint32, queryCount: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkResetQueryPool")) - vkGetSemaphoreCounterValue = cast[proc(device: VkDevice, semaphore: VkSemaphore, pValue: ptr uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSemaphoreCounterValue")) - vkWaitSemaphores = cast[proc(device: VkDevice, pWaitInfo: ptr VkSemaphoreWaitInfo, timeout: uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkWaitSemaphores")) - vkSignalSemaphore = cast[proc(device: VkDevice, pSignalInfo: ptr VkSemaphoreSignalInfo): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSignalSemaphore")) - vkGetBufferDeviceAddress = cast[proc(device: VkDevice, pInfo: ptr VkBufferDeviceAddressInfo): VkDeviceAddress {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferDeviceAddress")) - vkGetBufferOpaqueCaptureAddress = cast[proc(device: VkDevice, pInfo: ptr VkBufferDeviceAddressInfo): uint64 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferOpaqueCaptureAddress")) - vkGetDeviceMemoryOpaqueCaptureAddress = cast[proc(device: VkDevice, pInfo: ptr VkDeviceMemoryOpaqueCaptureAddressInfo): uint64 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceMemoryOpaqueCaptureAddress")) - -# feature VK_VERSION_1_3 -var - vkGetPhysicalDeviceToolProperties*: proc(physicalDevice: VkPhysicalDevice, pToolCount: ptr uint32, pToolProperties: ptr VkPhysicalDeviceToolProperties): VkResult {.stdcall.} - vkCreatePrivateDataSlot*: proc(device: VkDevice, pCreateInfo: ptr VkPrivateDataSlotCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPrivateDataSlot: ptr VkPrivateDataSlot): VkResult {.stdcall.} - vkDestroyPrivateDataSlot*: proc(device: VkDevice, privateDataSlot: VkPrivateDataSlot, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkSetPrivateData*: proc(device: VkDevice, objectType: VkObjectType, objectHandle: uint64, privateDataSlot: VkPrivateDataSlot, data: uint64): VkResult {.stdcall.} - vkGetPrivateData*: proc(device: VkDevice, objectType: VkObjectType, objectHandle: uint64, privateDataSlot: VkPrivateDataSlot, pData: ptr uint64): void {.stdcall.} - vkCmdSetEvent2*: proc(commandBuffer: VkCommandBuffer, event: VkEvent, pDependencyInfo: ptr VkDependencyInfo): void {.stdcall.} - vkCmdResetEvent2*: proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags2): void {.stdcall.} - vkCmdWaitEvents2*: proc(commandBuffer: VkCommandBuffer, eventCount: uint32, pEvents: ptr VkEvent, pDependencyInfos: ptr VkDependencyInfo): void {.stdcall.} - vkCmdPipelineBarrier2*: proc(commandBuffer: VkCommandBuffer, pDependencyInfo: ptr VkDependencyInfo): void {.stdcall.} - vkCmdWriteTimestamp2*: proc(commandBuffer: VkCommandBuffer, stage: VkPipelineStageFlags2, queryPool: VkQueryPool, query: uint32): void {.stdcall.} - vkQueueSubmit2*: proc(queue: VkQueue, submitCount: uint32, pSubmits: ptr VkSubmitInfo2, fence: VkFence): VkResult {.stdcall.} - vkCmdCopyBuffer2*: proc(commandBuffer: VkCommandBuffer, pCopyBufferInfo: ptr VkCopyBufferInfo2): void {.stdcall.} - vkCmdCopyImage2*: proc(commandBuffer: VkCommandBuffer, pCopyImageInfo: ptr VkCopyImageInfo2): void {.stdcall.} - vkCmdCopyBufferToImage2*: proc(commandBuffer: VkCommandBuffer, pCopyBufferToImageInfo: ptr VkCopyBufferToImageInfo2): void {.stdcall.} - vkCmdCopyImageToBuffer2*: proc(commandBuffer: VkCommandBuffer, pCopyImageToBufferInfo: ptr VkCopyImageToBufferInfo2): void {.stdcall.} - vkCmdBlitImage2*: proc(commandBuffer: VkCommandBuffer, pBlitImageInfo: ptr VkBlitImageInfo2): void {.stdcall.} - vkCmdResolveImage2*: proc(commandBuffer: VkCommandBuffer, pResolveImageInfo: ptr VkResolveImageInfo2): void {.stdcall.} - vkCmdBeginRendering*: proc(commandBuffer: VkCommandBuffer, pRenderingInfo: ptr VkRenderingInfo): void {.stdcall.} - vkCmdEndRendering*: proc(commandBuffer: VkCommandBuffer): void {.stdcall.} - vkCmdSetCullMode*: proc(commandBuffer: VkCommandBuffer, cullMode: VkCullModeFlags): void {.stdcall.} - vkCmdSetFrontFace*: proc(commandBuffer: VkCommandBuffer, frontFace: VkFrontFace): void {.stdcall.} - vkCmdSetPrimitiveTopology*: proc(commandBuffer: VkCommandBuffer, primitiveTopology: VkPrimitiveTopology): void {.stdcall.} - vkCmdSetViewportWithCount*: proc(commandBuffer: VkCommandBuffer, viewportCount: uint32, pViewports: ptr VkViewport): void {.stdcall.} - vkCmdSetScissorWithCount*: proc(commandBuffer: VkCommandBuffer, scissorCount: uint32, pScissors: ptr VkRect2D): void {.stdcall.} - vkCmdBindVertexBuffers2*: proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize, pSizes: ptr VkDeviceSize, pStrides: ptr VkDeviceSize): void {.stdcall.} - vkCmdSetDepthTestEnable*: proc(commandBuffer: VkCommandBuffer, depthTestEnable: VkBool32): void {.stdcall.} - vkCmdSetDepthWriteEnable*: proc(commandBuffer: VkCommandBuffer, depthWriteEnable: VkBool32): void {.stdcall.} - vkCmdSetDepthCompareOp*: proc(commandBuffer: VkCommandBuffer, depthCompareOp: VkCompareOp): void {.stdcall.} - vkCmdSetDepthBoundsTestEnable*: proc(commandBuffer: VkCommandBuffer, depthBoundsTestEnable: VkBool32): void {.stdcall.} - vkCmdSetStencilTestEnable*: proc(commandBuffer: VkCommandBuffer, stencilTestEnable: VkBool32): void {.stdcall.} - vkCmdSetStencilOp*: proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, failOp: VkStencilOp, passOp: VkStencilOp, depthFailOp: VkStencilOp, compareOp: VkCompareOp): void {.stdcall.} - vkCmdSetRasterizerDiscardEnable*: proc(commandBuffer: VkCommandBuffer, rasterizerDiscardEnable: VkBool32): void {.stdcall.} - vkCmdSetDepthBiasEnable*: proc(commandBuffer: VkCommandBuffer, depthBiasEnable: VkBool32): void {.stdcall.} - vkCmdSetPrimitiveRestartEnable*: proc(commandBuffer: VkCommandBuffer, primitiveRestartEnable: VkBool32): void {.stdcall.} - vkGetDeviceBufferMemoryRequirements*: proc(device: VkDevice, pInfo: ptr VkDeviceBufferMemoryRequirements, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.} - vkGetDeviceImageMemoryRequirements*: proc(device: VkDevice, pInfo: ptr VkDeviceImageMemoryRequirements, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.} - vkGetDeviceImageSparseMemoryRequirements*: proc(device: VkDevice, pInfo: ptr VkDeviceImageMemoryRequirements, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements2): void {.stdcall.} -proc loadVK_VERSION_1_3*(instance: VkInstance) = - vkGetPhysicalDeviceToolProperties = cast[proc(physicalDevice: VkPhysicalDevice, pToolCount: ptr uint32, pToolProperties: ptr VkPhysicalDeviceToolProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceToolProperties")) - vkCreatePrivateDataSlot = cast[proc(device: VkDevice, pCreateInfo: ptr VkPrivateDataSlotCreateInfo, pAllocator: ptr VkAllocationCallbacks, pPrivateDataSlot: ptr VkPrivateDataSlot): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreatePrivateDataSlot")) - vkDestroyPrivateDataSlot = cast[proc(device: VkDevice, privateDataSlot: VkPrivateDataSlot, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyPrivateDataSlot")) - vkSetPrivateData = cast[proc(device: VkDevice, objectType: VkObjectType, objectHandle: uint64, privateDataSlot: VkPrivateDataSlot, data: uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetPrivateData")) - vkGetPrivateData = cast[proc(device: VkDevice, objectType: VkObjectType, objectHandle: uint64, privateDataSlot: VkPrivateDataSlot, pData: ptr uint64): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPrivateData")) - vkCmdSetEvent2 = cast[proc(commandBuffer: VkCommandBuffer, event: VkEvent, pDependencyInfo: ptr VkDependencyInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetEvent2")) - vkCmdResetEvent2 = cast[proc(commandBuffer: VkCommandBuffer, event: VkEvent, stageMask: VkPipelineStageFlags2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdResetEvent2")) - vkCmdWaitEvents2 = cast[proc(commandBuffer: VkCommandBuffer, eventCount: uint32, pEvents: ptr VkEvent, pDependencyInfos: ptr VkDependencyInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWaitEvents2")) - vkCmdPipelineBarrier2 = cast[proc(commandBuffer: VkCommandBuffer, pDependencyInfo: ptr VkDependencyInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPipelineBarrier2")) - vkCmdWriteTimestamp2 = cast[proc(commandBuffer: VkCommandBuffer, stage: VkPipelineStageFlags2, queryPool: VkQueryPool, query: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteTimestamp2")) - vkQueueSubmit2 = cast[proc(queue: VkQueue, submitCount: uint32, pSubmits: ptr VkSubmitInfo2, fence: VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueSubmit2")) - vkCmdCopyBuffer2 = cast[proc(commandBuffer: VkCommandBuffer, pCopyBufferInfo: ptr VkCopyBufferInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyBuffer2")) - vkCmdCopyImage2 = cast[proc(commandBuffer: VkCommandBuffer, pCopyImageInfo: ptr VkCopyImageInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyImage2")) - vkCmdCopyBufferToImage2 = cast[proc(commandBuffer: VkCommandBuffer, pCopyBufferToImageInfo: ptr VkCopyBufferToImageInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyBufferToImage2")) - vkCmdCopyImageToBuffer2 = cast[proc(commandBuffer: VkCommandBuffer, pCopyImageToBufferInfo: ptr VkCopyImageToBufferInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyImageToBuffer2")) - vkCmdBlitImage2 = cast[proc(commandBuffer: VkCommandBuffer, pBlitImageInfo: ptr VkBlitImageInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBlitImage2")) - vkCmdResolveImage2 = cast[proc(commandBuffer: VkCommandBuffer, pResolveImageInfo: ptr VkResolveImageInfo2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdResolveImage2")) - vkCmdBeginRendering = cast[proc(commandBuffer: VkCommandBuffer, pRenderingInfo: ptr VkRenderingInfo): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginRendering")) - vkCmdEndRendering = cast[proc(commandBuffer: VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndRendering")) - vkCmdSetCullMode = cast[proc(commandBuffer: VkCommandBuffer, cullMode: VkCullModeFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCullMode")) - vkCmdSetFrontFace = cast[proc(commandBuffer: VkCommandBuffer, frontFace: VkFrontFace): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetFrontFace")) - vkCmdSetPrimitiveTopology = cast[proc(commandBuffer: VkCommandBuffer, primitiveTopology: VkPrimitiveTopology): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPrimitiveTopology")) - vkCmdSetViewportWithCount = cast[proc(commandBuffer: VkCommandBuffer, viewportCount: uint32, pViewports: ptr VkViewport): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewportWithCount")) - vkCmdSetScissorWithCount = cast[proc(commandBuffer: VkCommandBuffer, scissorCount: uint32, pScissors: ptr VkRect2D): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetScissorWithCount")) - vkCmdBindVertexBuffers2 = cast[proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize, pSizes: ptr VkDeviceSize, pStrides: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindVertexBuffers2")) - vkCmdSetDepthTestEnable = cast[proc(commandBuffer: VkCommandBuffer, depthTestEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthTestEnable")) - vkCmdSetDepthWriteEnable = cast[proc(commandBuffer: VkCommandBuffer, depthWriteEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthWriteEnable")) - vkCmdSetDepthCompareOp = cast[proc(commandBuffer: VkCommandBuffer, depthCompareOp: VkCompareOp): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthCompareOp")) - vkCmdSetDepthBoundsTestEnable = cast[proc(commandBuffer: VkCommandBuffer, depthBoundsTestEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthBoundsTestEnable")) - vkCmdSetStencilTestEnable = cast[proc(commandBuffer: VkCommandBuffer, stencilTestEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetStencilTestEnable")) - vkCmdSetStencilOp = cast[proc(commandBuffer: VkCommandBuffer, faceMask: VkStencilFaceFlags, failOp: VkStencilOp, passOp: VkStencilOp, depthFailOp: VkStencilOp, compareOp: VkCompareOp): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetStencilOp")) - vkCmdSetRasterizerDiscardEnable = cast[proc(commandBuffer: VkCommandBuffer, rasterizerDiscardEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetRasterizerDiscardEnable")) - vkCmdSetDepthBiasEnable = cast[proc(commandBuffer: VkCommandBuffer, depthBiasEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthBiasEnable")) - vkCmdSetPrimitiveRestartEnable = cast[proc(commandBuffer: VkCommandBuffer, primitiveRestartEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPrimitiveRestartEnable")) - vkGetDeviceBufferMemoryRequirements = cast[proc(device: VkDevice, pInfo: ptr VkDeviceBufferMemoryRequirements, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceBufferMemoryRequirements")) - vkGetDeviceImageMemoryRequirements = cast[proc(device: VkDevice, pInfo: ptr VkDeviceImageMemoryRequirements, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceImageMemoryRequirements")) - vkGetDeviceImageSparseMemoryRequirements = cast[proc(device: VkDevice, pInfo: ptr VkDeviceImageMemoryRequirements, pSparseMemoryRequirementCount: ptr uint32, pSparseMemoryRequirements: ptr VkSparseImageMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceImageSparseMemoryRequirements")) - - -proc loadVulkan*(instance: VkInstance) = - loadVK_VERSION_1_0(instance) - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_2(instance) - loadVK_VERSION_1_3(instance) - -proc loadVK_NV_geometry_shader_passthrough*(instance: VkInstance) = - discard - -proc loadVK_EXT_rasterization_order_attachment_access*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_IMG_format_pvrtc*(instance: VkInstance) = - discard - -proc loadVK_AMD_shader_fragment_mask*(instance: VkInstance) = - discard - -proc loadVK_EXT_primitive_topology_list_restart*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_KHR_global_priority*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_QCOM_image_processing*(instance: VkInstance) = - loadVK_VERSION_1_3(instance) - -# extension VK_AMD_shader_info -var - vkGetShaderInfoAMD*: proc(device: VkDevice, pipeline: VkPipeline, shaderStage: VkShaderStageFlagBits, infoType: VkShaderInfoTypeAMD, pInfoSize: ptr csize_t, pInfo: pointer): VkResult {.stdcall.} -proc loadVK_AMD_shader_info*(instance: VkInstance) = - vkGetShaderInfoAMD = cast[proc(device: VkDevice, pipeline: VkPipeline, shaderStage: VkShaderStageFlagBits, infoType: VkShaderInfoTypeAMD, pInfoSize: ptr csize_t, pInfo: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetShaderInfoAMD")) - -proc loadVK_AMD_gpu_shader_int16*(instance: VkInstance) = - discard - -proc loadVK_EXT_pipeline_robustness*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_EXT_sample_locations -var - vkCmdSetSampleLocationsEXT*: proc(commandBuffer: VkCommandBuffer, pSampleLocationsInfo: ptr VkSampleLocationsInfoEXT): void {.stdcall.} - vkGetPhysicalDeviceMultisamplePropertiesEXT*: proc(physicalDevice: VkPhysicalDevice, samples: VkSampleCountFlagBits, pMultisampleProperties: ptr VkMultisamplePropertiesEXT): void {.stdcall.} -proc loadVK_EXT_sample_locations*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdSetSampleLocationsEXT = cast[proc(commandBuffer: VkCommandBuffer, pSampleLocationsInfo: ptr VkSampleLocationsInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetSampleLocationsEXT")) - vkGetPhysicalDeviceMultisamplePropertiesEXT = cast[proc(physicalDevice: VkPhysicalDevice, samples: VkSampleCountFlagBits, pMultisampleProperties: ptr VkMultisamplePropertiesEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMultisamplePropertiesEXT")) - -# extension VK_EXT_descriptor_buffer -var - vkGetDescriptorSetLayoutSizeEXT*: proc(device: VkDevice, layout: VkDescriptorSetLayout, pLayoutSizeInBytes: ptr VkDeviceSize): void {.stdcall.} - vkGetDescriptorSetLayoutBindingOffsetEXT*: proc(device: VkDevice, layout: VkDescriptorSetLayout, binding: uint32, pOffset: ptr VkDeviceSize): void {.stdcall.} - vkGetDescriptorEXT*: proc(device: VkDevice, pDescriptorInfo: ptr VkDescriptorGetInfoEXT, dataSize: csize_t, pDescriptor: pointer): void {.stdcall.} - vkCmdBindDescriptorBuffersEXT*: proc(commandBuffer: VkCommandBuffer, bufferCount: uint32, pBindingInfos: ptr VkDescriptorBufferBindingInfoEXT): void {.stdcall.} - vkCmdSetDescriptorBufferOffsetsEXT*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, firstSet: uint32, setCount: uint32, pBufferIndices: ptr uint32, pOffsets: ptr VkDeviceSize): void {.stdcall.} - vkCmdBindDescriptorBufferEmbeddedSamplersEXT*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, set: uint32): void {.stdcall.} - vkGetBufferOpaqueCaptureDescriptorDataEXT*: proc(device: VkDevice, pInfo: ptr VkBufferCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.} - vkGetImageOpaqueCaptureDescriptorDataEXT*: proc(device: VkDevice, pInfo: ptr VkImageCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.} - vkGetImageViewOpaqueCaptureDescriptorDataEXT*: proc(device: VkDevice, pInfo: ptr VkImageViewCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.} - vkGetSamplerOpaqueCaptureDescriptorDataEXT*: proc(device: VkDevice, pInfo: ptr VkSamplerCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.} - vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT*: proc(device: VkDevice, pInfo: ptr VkAccelerationStructureCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.} -proc loadVK_EXT_descriptor_buffer*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_2(instance) - loadVK_VERSION_1_3(instance) - loadVK_VERSION_1_2(instance) - vkGetDescriptorSetLayoutSizeEXT = cast[proc(device: VkDevice, layout: VkDescriptorSetLayout, pLayoutSizeInBytes: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorSetLayoutSizeEXT")) - vkGetDescriptorSetLayoutBindingOffsetEXT = cast[proc(device: VkDevice, layout: VkDescriptorSetLayout, binding: uint32, pOffset: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorSetLayoutBindingOffsetEXT")) - vkGetDescriptorEXT = cast[proc(device: VkDevice, pDescriptorInfo: ptr VkDescriptorGetInfoEXT, dataSize: csize_t, pDescriptor: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorEXT")) - vkCmdBindDescriptorBuffersEXT = cast[proc(commandBuffer: VkCommandBuffer, bufferCount: uint32, pBindingInfos: ptr VkDescriptorBufferBindingInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindDescriptorBuffersEXT")) - vkCmdSetDescriptorBufferOffsetsEXT = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, firstSet: uint32, setCount: uint32, pBufferIndices: ptr uint32, pOffsets: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDescriptorBufferOffsetsEXT")) - vkCmdBindDescriptorBufferEmbeddedSamplersEXT = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, set: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindDescriptorBufferEmbeddedSamplersEXT")) - vkGetBufferOpaqueCaptureDescriptorDataEXT = cast[proc(device: VkDevice, pInfo: ptr VkBufferCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferOpaqueCaptureDescriptorDataEXT")) - vkGetImageOpaqueCaptureDescriptorDataEXT = cast[proc(device: VkDevice, pInfo: ptr VkImageCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageOpaqueCaptureDescriptorDataEXT")) - vkGetImageViewOpaqueCaptureDescriptorDataEXT = cast[proc(device: VkDevice, pInfo: ptr VkImageViewCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageViewOpaqueCaptureDescriptorDataEXT")) - vkGetSamplerOpaqueCaptureDescriptorDataEXT = cast[proc(device: VkDevice, pInfo: ptr VkSamplerCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSamplerOpaqueCaptureDescriptorDataEXT")) - vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT = cast[proc(device: VkDevice, pInfo: ptr VkAccelerationStructureCaptureDescriptorDataInfoEXT, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT")) - -# extension VK_KHR_performance_query -var - vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, pCounterCount: ptr uint32, pCounters: ptr VkPerformanceCounterKHR, pCounterDescriptions: ptr VkPerformanceCounterDescriptionKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR*: proc(physicalDevice: VkPhysicalDevice, pPerformanceQueryCreateInfo: ptr VkQueryPoolPerformanceCreateInfoKHR, pNumPasses: ptr uint32): void {.stdcall.} - vkAcquireProfilingLockKHR*: proc(device: VkDevice, pInfo: ptr VkAcquireProfilingLockInfoKHR): VkResult {.stdcall.} - vkReleaseProfilingLockKHR*: proc(device: VkDevice): void {.stdcall.} -proc loadVK_KHR_performance_query*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, pCounterCount: ptr uint32, pCounters: ptr VkPerformanceCounterKHR, pCounterDescriptions: ptr VkPerformanceCounterDescriptionKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR")) - vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pPerformanceQueryCreateInfo: ptr VkQueryPoolPerformanceCreateInfoKHR, pNumPasses: ptr uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR")) - vkAcquireProfilingLockKHR = cast[proc(device: VkDevice, pInfo: ptr VkAcquireProfilingLockInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireProfilingLockKHR")) - vkReleaseProfilingLockKHR = cast[proc(device: VkDevice): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkReleaseProfilingLockKHR")) - -proc loadVK_GOOGLE_user_type*(instance: VkInstance) = - discard - -# extension VK_EXT_debug_report -var - vkCreateDebugReportCallbackEXT*: proc(instance: VkInstance, pCreateInfo: ptr VkDebugReportCallbackCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pCallback: ptr VkDebugReportCallbackEXT): VkResult {.stdcall.} - vkDestroyDebugReportCallbackEXT*: proc(instance: VkInstance, callback: VkDebugReportCallbackEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkDebugReportMessageEXT*: proc(instance: VkInstance, flags: VkDebugReportFlagsEXT, objectType: VkDebugReportObjectTypeEXT, theobject: uint64, location: csize_t, messageCode: int32, pLayerPrefix: cstring, pMessage: cstring): void {.stdcall.} -proc loadVK_EXT_debug_report*(instance: VkInstance) = - vkCreateDebugReportCallbackEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDebugReportCallbackCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pCallback: ptr VkDebugReportCallbackEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT")) - vkDestroyDebugReportCallbackEXT = cast[proc(instance: VkInstance, callback: VkDebugReportCallbackEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT")) - vkDebugReportMessageEXT = cast[proc(instance: VkInstance, flags: VkDebugReportFlagsEXT, objectType: VkDebugReportObjectTypeEXT, theobject: uint64, location: csize_t, messageCode: int32, pLayerPrefix: cstring, pMessage: cstring): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDebugReportMessageEXT")) - -proc loadVK_EXT_multisampled_render_to_single_sampled*(instance: VkInstance) = - loadVK_VERSION_1_2(instance) - loadVK_VERSION_1_2(instance) - -proc loadVK_AMD_negative_viewport_height*(instance: VkInstance) = - discard - -proc loadVK_EXT_provoking_vertex*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_NV_device_diagnostics_config*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_NV_shader_subgroup_partitioned*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_image_sliced_view_of_3d*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_1(instance) - -proc loadVK_AMD_shader_image_load_store_lod*(instance: VkInstance) = - discard - -proc loadVK_INTEL_shader_integer_functions2*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_image_2d_view_of_3d*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_1(instance) - -# extension VK_NV_shading_rate_image -var - vkCmdBindShadingRateImageNV*: proc(commandBuffer: VkCommandBuffer, imageView: VkImageView, imageLayout: VkImageLayout): void {.stdcall.} - vkCmdSetViewportShadingRatePaletteNV*: proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pShadingRatePalettes: ptr VkShadingRatePaletteNV): void {.stdcall.} - vkCmdSetCoarseSampleOrderNV*: proc(commandBuffer: VkCommandBuffer, sampleOrderType: VkCoarseSampleOrderTypeNV, customSampleOrderCount: uint32, pCustomSampleOrders: ptr VkCoarseSampleOrderCustomNV): void {.stdcall.} -proc loadVK_NV_shading_rate_image*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdBindShadingRateImageNV = cast[proc(commandBuffer: VkCommandBuffer, imageView: VkImageView, imageLayout: VkImageLayout): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindShadingRateImageNV")) - vkCmdSetViewportShadingRatePaletteNV = cast[proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pShadingRatePalettes: ptr VkShadingRatePaletteNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewportShadingRatePaletteNV")) - vkCmdSetCoarseSampleOrderNV = cast[proc(commandBuffer: VkCommandBuffer, sampleOrderType: VkCoarseSampleOrderTypeNV, customSampleOrderCount: uint32, pCustomSampleOrders: ptr VkCoarseSampleOrderCustomNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoarseSampleOrderNV")) - -proc loadVK_EXT_fragment_density_map*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_NV_device_diagnostic_checkpoints -var - vkCmdSetCheckpointNV*: proc(commandBuffer: VkCommandBuffer, pCheckpointMarker: pointer): void {.stdcall.} - vkGetQueueCheckpointDataNV*: proc(queue: VkQueue, pCheckpointDataCount: ptr uint32, pCheckpointData: ptr VkCheckpointDataNV): void {.stdcall.} -proc loadVK_NV_device_diagnostic_checkpoints*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdSetCheckpointNV = cast[proc(commandBuffer: VkCommandBuffer, pCheckpointMarker: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCheckpointNV")) - vkGetQueueCheckpointDataNV = cast[proc(queue: VkQueue, pCheckpointDataCount: ptr uint32, pCheckpointData: ptr VkCheckpointDataNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetQueueCheckpointDataNV")) - -proc loadVK_EXT_pci_bus_info*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_queue_family_foreign*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_EXT_debug_utils -var - vkSetDebugUtilsObjectNameEXT*: proc(device: VkDevice, pNameInfo: ptr VkDebugUtilsObjectNameInfoEXT): VkResult {.stdcall.} - vkSetDebugUtilsObjectTagEXT*: proc(device: VkDevice, pTagInfo: ptr VkDebugUtilsObjectTagInfoEXT): VkResult {.stdcall.} - vkQueueBeginDebugUtilsLabelEXT*: proc(queue: VkQueue, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.} - vkQueueEndDebugUtilsLabelEXT*: proc(queue: VkQueue): void {.stdcall.} - vkQueueInsertDebugUtilsLabelEXT*: proc(queue: VkQueue, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.} - vkCmdBeginDebugUtilsLabelEXT*: proc(commandBuffer: VkCommandBuffer, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.} - vkCmdEndDebugUtilsLabelEXT*: proc(commandBuffer: VkCommandBuffer): void {.stdcall.} - vkCmdInsertDebugUtilsLabelEXT*: proc(commandBuffer: VkCommandBuffer, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.} - vkCreateDebugUtilsMessengerEXT*: proc(instance: VkInstance, pCreateInfo: ptr VkDebugUtilsMessengerCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pMessenger: ptr VkDebugUtilsMessengerEXT): VkResult {.stdcall.} - vkDestroyDebugUtilsMessengerEXT*: proc(instance: VkInstance, messenger: VkDebugUtilsMessengerEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkSubmitDebugUtilsMessageEXT*: proc(instance: VkInstance, messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, messageTypes: VkDebugUtilsMessageTypeFlagsEXT, pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT): void {.stdcall.} -proc loadVK_EXT_debug_utils*(instance: VkInstance) = - vkSetDebugUtilsObjectNameEXT = cast[proc(device: VkDevice, pNameInfo: ptr VkDebugUtilsObjectNameInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT")) - vkSetDebugUtilsObjectTagEXT = cast[proc(device: VkDevice, pTagInfo: ptr VkDebugUtilsObjectTagInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectTagEXT")) - vkQueueBeginDebugUtilsLabelEXT = cast[proc(queue: VkQueue, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueBeginDebugUtilsLabelEXT")) - vkQueueEndDebugUtilsLabelEXT = cast[proc(queue: VkQueue): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueEndDebugUtilsLabelEXT")) - vkQueueInsertDebugUtilsLabelEXT = cast[proc(queue: VkQueue, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueInsertDebugUtilsLabelEXT")) - vkCmdBeginDebugUtilsLabelEXT = cast[proc(commandBuffer: VkCommandBuffer, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT")) - vkCmdEndDebugUtilsLabelEXT = cast[proc(commandBuffer: VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT")) - vkCmdInsertDebugUtilsLabelEXT = cast[proc(commandBuffer: VkCommandBuffer, pLabelInfo: ptr VkDebugUtilsLabelEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdInsertDebugUtilsLabelEXT")) - vkCreateDebugUtilsMessengerEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDebugUtilsMessengerCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pMessenger: ptr VkDebugUtilsMessengerEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT")) - vkDestroyDebugUtilsMessengerEXT = cast[proc(instance: VkInstance, messenger: VkDebugUtilsMessengerEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT")) - vkSubmitDebugUtilsMessageEXT = cast[proc(instance: VkInstance, messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, messageTypes: VkDebugUtilsMessageTypeFlagsEXT, pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSubmitDebugUtilsMessageEXT")) - -proc loadVK_KHR_portability_enumeration*(instance: VkInstance) = - discard - -proc loadVK_EXT_memory_priority*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_AMD_shader_core_properties*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_KHR_external_fence_fd -var - vkImportFenceFdKHR*: proc(device: VkDevice, pImportFenceFdInfo: ptr VkImportFenceFdInfoKHR): VkResult {.stdcall.} - vkGetFenceFdKHR*: proc(device: VkDevice, pGetFdInfo: ptr VkFenceGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.} -proc loadVK_KHR_external_fence_fd*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkImportFenceFdKHR = cast[proc(device: VkDevice, pImportFenceFdInfo: ptr VkImportFenceFdInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkImportFenceFdKHR")) - vkGetFenceFdKHR = cast[proc(device: VkDevice, pGetFdInfo: ptr VkFenceGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetFenceFdKHR")) - -# extension VK_NV_device_generated_commands -var - vkGetGeneratedCommandsMemoryRequirementsNV*: proc(device: VkDevice, pInfo: ptr VkGeneratedCommandsMemoryRequirementsInfoNV, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.} - vkCmdPreprocessGeneratedCommandsNV*: proc(commandBuffer: VkCommandBuffer, pGeneratedCommandsInfo: ptr VkGeneratedCommandsInfoNV): void {.stdcall.} - vkCmdExecuteGeneratedCommandsNV*: proc(commandBuffer: VkCommandBuffer, isPreprocessed: VkBool32, pGeneratedCommandsInfo: ptr VkGeneratedCommandsInfoNV): void {.stdcall.} - vkCmdBindPipelineShaderGroupNV*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, pipeline: VkPipeline, groupIndex: uint32): void {.stdcall.} - vkCreateIndirectCommandsLayoutNV*: proc(device: VkDevice, pCreateInfo: ptr VkIndirectCommandsLayoutCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pIndirectCommandsLayout: ptr VkIndirectCommandsLayoutNV): VkResult {.stdcall.} - vkDestroyIndirectCommandsLayoutNV*: proc(device: VkDevice, indirectCommandsLayout: VkIndirectCommandsLayoutNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} -proc loadVK_NV_device_generated_commands*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_2(instance) - vkGetGeneratedCommandsMemoryRequirementsNV = cast[proc(device: VkDevice, pInfo: ptr VkGeneratedCommandsMemoryRequirementsInfoNV, pMemoryRequirements: ptr VkMemoryRequirements2): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetGeneratedCommandsMemoryRequirementsNV")) - vkCmdPreprocessGeneratedCommandsNV = cast[proc(commandBuffer: VkCommandBuffer, pGeneratedCommandsInfo: ptr VkGeneratedCommandsInfoNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPreprocessGeneratedCommandsNV")) - vkCmdExecuteGeneratedCommandsNV = cast[proc(commandBuffer: VkCommandBuffer, isPreprocessed: VkBool32, pGeneratedCommandsInfo: ptr VkGeneratedCommandsInfoNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdExecuteGeneratedCommandsNV")) - vkCmdBindPipelineShaderGroupNV = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, pipeline: VkPipeline, groupIndex: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindPipelineShaderGroupNV")) - vkCreateIndirectCommandsLayoutNV = cast[proc(device: VkDevice, pCreateInfo: ptr VkIndirectCommandsLayoutCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pIndirectCommandsLayout: ptr VkIndirectCommandsLayoutNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateIndirectCommandsLayoutNV")) - vkDestroyIndirectCommandsLayoutNV = cast[proc(device: VkDevice, indirectCommandsLayout: VkIndirectCommandsLayoutNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyIndirectCommandsLayoutNV")) - -proc loadVK_NV_viewport_array2*(instance: VkInstance) = - discard - -proc loadVK_NVX_multiview_per_view_attributes*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_KHR_external_memory_fd -var - vkGetMemoryFdKHR*: proc(device: VkDevice, pGetFdInfo: ptr VkMemoryGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.} - vkGetMemoryFdPropertiesKHR*: proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, fd: cint, pMemoryFdProperties: ptr VkMemoryFdPropertiesKHR): VkResult {.stdcall.} -proc loadVK_KHR_external_memory_fd*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetMemoryFdKHR = cast[proc(device: VkDevice, pGetFdInfo: ptr VkMemoryGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryFdKHR")) - vkGetMemoryFdPropertiesKHR = cast[proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, fd: cint, pMemoryFdProperties: ptr VkMemoryFdPropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryFdPropertiesKHR")) - -proc loadVK_EXT_rgba10x6_formats*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_NV_dedicated_allocation_image_aliasing*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_1(instance) - -# extension VK_NV_cooperative_matrix -var - vkGetPhysicalDeviceCooperativeMatrixPropertiesNV*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkCooperativeMatrixPropertiesNV): VkResult {.stdcall.} -proc loadVK_NV_cooperative_matrix*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetPhysicalDeviceCooperativeMatrixPropertiesNV = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkCooperativeMatrixPropertiesNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV")) - -proc loadVK_EXT_depth_clamp_zero_one*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_NV_linear_color_attachment*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_shader_subgroup_ballot*(instance: VkInstance) = - discard - -# extension VK_EXT_image_drm_format_modifier -var - vkGetImageDrmFormatModifierPropertiesEXT*: proc(device: VkDevice, image: VkImage, pProperties: ptr VkImageDrmFormatModifierPropertiesEXT): VkResult {.stdcall.} -proc loadVK_EXT_image_drm_format_modifier*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_2(instance) - loadVK_VERSION_1_1(instance) - vkGetImageDrmFormatModifierPropertiesEXT = cast[proc(device: VkDevice, image: VkImage, pProperties: ptr VkImageDrmFormatModifierPropertiesEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageDrmFormatModifierPropertiesEXT")) - -# extension VK_EXT_mesh_shader -var - vkCmdDrawMeshTasksEXT*: proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.} - vkCmdDrawMeshTasksIndirectEXT*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.} - vkCmdDrawMeshTasksIndirectCountEXT*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.} -proc loadVK_EXT_mesh_shader*(instance: VkInstance) = - loadVK_VERSION_1_2(instance) - vkCmdDrawMeshTasksEXT = cast[proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksEXT")) - vkCmdDrawMeshTasksIndirectEXT = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectEXT")) - vkCmdDrawMeshTasksIndirectCountEXT = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectCountEXT")) - -# extension VK_EXT_transform_feedback -var - vkCmdBindTransformFeedbackBuffersEXT*: proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize, pSizes: ptr VkDeviceSize): void {.stdcall.} - vkCmdBeginTransformFeedbackEXT*: proc(commandBuffer: VkCommandBuffer, firstCounterBuffer: uint32, counterBufferCount: uint32, pCounterBuffers: ptr VkBuffer, pCounterBufferOffsets: ptr VkDeviceSize): void {.stdcall.} - vkCmdEndTransformFeedbackEXT*: proc(commandBuffer: VkCommandBuffer, firstCounterBuffer: uint32, counterBufferCount: uint32, pCounterBuffers: ptr VkBuffer, pCounterBufferOffsets: ptr VkDeviceSize): void {.stdcall.} - vkCmdBeginQueryIndexedEXT*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, flags: VkQueryControlFlags, index: uint32): void {.stdcall.} - vkCmdEndQueryIndexedEXT*: proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, index: uint32): void {.stdcall.} - vkCmdDrawIndirectByteCountEXT*: proc(commandBuffer: VkCommandBuffer, instanceCount: uint32, firstInstance: uint32, counterBuffer: VkBuffer, counterBufferOffset: VkDeviceSize, counterOffset: uint32, vertexStride: uint32): void {.stdcall.} -proc loadVK_EXT_transform_feedback*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdBindTransformFeedbackBuffersEXT = cast[proc(commandBuffer: VkCommandBuffer, firstBinding: uint32, bindingCount: uint32, pBuffers: ptr VkBuffer, pOffsets: ptr VkDeviceSize, pSizes: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindTransformFeedbackBuffersEXT")) - vkCmdBeginTransformFeedbackEXT = cast[proc(commandBuffer: VkCommandBuffer, firstCounterBuffer: uint32, counterBufferCount: uint32, pCounterBuffers: ptr VkBuffer, pCounterBufferOffsets: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginTransformFeedbackEXT")) - vkCmdEndTransformFeedbackEXT = cast[proc(commandBuffer: VkCommandBuffer, firstCounterBuffer: uint32, counterBufferCount: uint32, pCounterBuffers: ptr VkBuffer, pCounterBufferOffsets: ptr VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndTransformFeedbackEXT")) - vkCmdBeginQueryIndexedEXT = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, flags: VkQueryControlFlags, index: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginQueryIndexedEXT")) - vkCmdEndQueryIndexedEXT = cast[proc(commandBuffer: VkCommandBuffer, queryPool: VkQueryPool, query: uint32, index: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndQueryIndexedEXT")) - vkCmdDrawIndirectByteCountEXT = cast[proc(commandBuffer: VkCommandBuffer, instanceCount: uint32, firstInstance: uint32, counterBuffer: VkBuffer, counterBufferOffset: VkDeviceSize, counterOffset: uint32, vertexStride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawIndirectByteCountEXT")) - -proc loadVK_AMD_shader_early_and_late_fragment_tests*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_AMD_shader_core_properties2*(instance: VkInstance) = - loadVK_AMD_shader_core_properties(instance) - -proc loadVK_GOOGLE_hlsl_functionality1*(instance: VkInstance) = - discard - -proc loadVK_EXT_robustness2*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_image_view_min_lod*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_AMD_shader_trinary_minmax*(instance: VkInstance) = - discard - -proc loadVK_EXT_custom_border_color*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_AMD_rasterization_order*(instance: VkInstance) = - discard - -# extension VK_EXT_vertex_input_dynamic_state -var - vkCmdSetVertexInputEXT*: proc(commandBuffer: VkCommandBuffer, vertexBindingDescriptionCount: uint32, pVertexBindingDescriptions: ptr VkVertexInputBindingDescription2EXT, vertexAttributeDescriptionCount: uint32, pVertexAttributeDescriptions: ptr VkVertexInputAttributeDescription2EXT): void {.stdcall.} -proc loadVK_EXT_vertex_input_dynamic_state*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdSetVertexInputEXT = cast[proc(commandBuffer: VkCommandBuffer, vertexBindingDescriptionCount: uint32, pVertexBindingDescriptions: ptr VkVertexInputBindingDescription2EXT, vertexAttributeDescriptionCount: uint32, pVertexAttributeDescriptions: ptr VkVertexInputAttributeDescription2EXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetVertexInputEXT")) - -# extension VK_KHR_fragment_shading_rate -var - vkGetPhysicalDeviceFragmentShadingRatesKHR*: proc(physicalDevice: VkPhysicalDevice, pFragmentShadingRateCount: ptr uint32, pFragmentShadingRates: ptr VkPhysicalDeviceFragmentShadingRateKHR): VkResult {.stdcall.} - vkCmdSetFragmentShadingRateKHR*: proc(commandBuffer: VkCommandBuffer, pFragmentSize: ptr VkExtent2D, combinerOps: array[2, VkFragmentShadingRateCombinerOpKHR]): void {.stdcall.} -proc loadVK_KHR_fragment_shading_rate*(instance: VkInstance) = - loadVK_VERSION_1_2(instance) - loadVK_VERSION_1_1(instance) - vkGetPhysicalDeviceFragmentShadingRatesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pFragmentShadingRateCount: ptr uint32, pFragmentShadingRates: ptr VkPhysicalDeviceFragmentShadingRateKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFragmentShadingRatesKHR")) - vkCmdSetFragmentShadingRateKHR = cast[proc(commandBuffer: VkCommandBuffer, pFragmentSize: ptr VkExtent2D, combinerOps: array[2, VkFragmentShadingRateCombinerOpKHR]): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetFragmentShadingRateKHR")) - -proc loadVK_EXT_depth_clip_enable*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_subpass_merge_feedback*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_KHR_external_semaphore_fd -var - vkImportSemaphoreFdKHR*: proc(device: VkDevice, pImportSemaphoreFdInfo: ptr VkImportSemaphoreFdInfoKHR): VkResult {.stdcall.} - vkGetSemaphoreFdKHR*: proc(device: VkDevice, pGetFdInfo: ptr VkSemaphoreGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.} -proc loadVK_KHR_external_semaphore_fd*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkImportSemaphoreFdKHR = cast[proc(device: VkDevice, pImportSemaphoreFdInfo: ptr VkImportSemaphoreFdInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkImportSemaphoreFdKHR")) - vkGetSemaphoreFdKHR = cast[proc(device: VkDevice, pGetFdInfo: ptr VkSemaphoreGetFdInfoKHR, pFd: ptr cint): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSemaphoreFdKHR")) - -proc loadVK_KHR_fragment_shader_barycentric*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_memory_budget*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_AMD_device_coherent_memory*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_device_memory_report*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_AMD_memory_overallocation_behavior*(instance: VkInstance) = - discard - -# extension VK_NV_mesh_shader -var - vkCmdDrawMeshTasksNV*: proc(commandBuffer: VkCommandBuffer, taskCount: uint32, firstTask: uint32): void {.stdcall.} - vkCmdDrawMeshTasksIndirectNV*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.} - vkCmdDrawMeshTasksIndirectCountNV*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.} -proc loadVK_NV_mesh_shader*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdDrawMeshTasksNV = cast[proc(commandBuffer: VkCommandBuffer, taskCount: uint32, firstTask: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksNV")) - vkCmdDrawMeshTasksIndirectNV = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, drawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectNV")) - vkCmdDrawMeshTasksIndirectCountNV = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize, countBuffer: VkBuffer, countBufferOffset: VkDeviceSize, maxDrawCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectCountNV")) - -# extension VK_EXT_image_compression_control -var - vkGetImageSubresourceLayout2EXT*: proc(device: VkDevice, image: VkImage, pSubresource: ptr VkImageSubresource2EXT, pLayout: ptr VkSubresourceLayout2EXT): void {.stdcall.} -proc loadVK_EXT_image_compression_control*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetImageSubresourceLayout2EXT = cast[proc(device: VkDevice, image: VkImage, pSubresource: ptr VkImageSubresource2EXT, pLayout: ptr VkSubresourceLayout2EXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageSubresourceLayout2EXT")) - -# extension VK_EXT_buffer_device_address -var - vkGetBufferDeviceAddressEXT*: proc(device: VkDevice, pInfo: ptr VkBufferDeviceAddressInfo): VkDeviceAddress {.stdcall.} -proc loadVK_EXT_buffer_device_address*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetBufferDeviceAddressEXT = vkGetBufferDeviceAddress - -proc loadVK_QCOM_render_pass_shader_resolve*(instance: VkInstance) = - discard - -proc loadVK_EXT_depth_range_unrestricted*(instance: VkInstance) = - discard - -# extension VK_HUAWEI_subpass_shading -var - vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI*: proc(device: VkDevice, renderpass: VkRenderPass, pMaxWorkgroupSize: ptr VkExtent2D): VkResult {.stdcall.} - vkCmdSubpassShadingHUAWEI*: proc(commandBuffer: VkCommandBuffer): void {.stdcall.} -proc loadVK_HUAWEI_subpass_shading*(instance: VkInstance) = - loadVK_VERSION_1_2(instance) - loadVK_VERSION_1_3(instance) - vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = cast[proc(device: VkDevice, renderpass: VkRenderPass, pMaxWorkgroupSize: ptr VkExtent2D): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI")) - vkCmdSubpassShadingHUAWEI = cast[proc(commandBuffer: VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSubpassShadingHUAWEI")) - -# extension VK_VALVE_descriptor_set_host_mapping -var - vkGetDescriptorSetLayoutHostMappingInfoVALVE*: proc(device: VkDevice, pBindingReference: ptr VkDescriptorSetBindingReferenceVALVE, pHostMapping: ptr VkDescriptorSetLayoutHostMappingInfoVALVE): void {.stdcall.} - vkGetDescriptorSetHostMappingVALVE*: proc(device: VkDevice, descriptorSet: VkDescriptorSet, ppData: ptr pointer): void {.stdcall.} -proc loadVK_VALVE_descriptor_set_host_mapping*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetDescriptorSetLayoutHostMappingInfoVALVE = cast[proc(device: VkDevice, pBindingReference: ptr VkDescriptorSetBindingReferenceVALVE, pHostMapping: ptr VkDescriptorSetLayoutHostMappingInfoVALVE): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorSetLayoutHostMappingInfoVALVE")) - vkGetDescriptorSetHostMappingVALVE = cast[proc(device: VkDevice, descriptorSet: VkDescriptorSet, ppData: ptr pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDescriptorSetHostMappingVALVE")) - -# extension VK_NV_external_memory_capabilities -var - vkGetPhysicalDeviceExternalImageFormatPropertiesNV*: proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, tiling: VkImageTiling, usage: VkImageUsageFlags, flags: VkImageCreateFlags, externalHandleType: VkExternalMemoryHandleTypeFlagsNV, pExternalImageFormatProperties: ptr VkExternalImageFormatPropertiesNV): VkResult {.stdcall.} -proc loadVK_NV_external_memory_capabilities*(instance: VkInstance) = - vkGetPhysicalDeviceExternalImageFormatPropertiesNV = cast[proc(physicalDevice: VkPhysicalDevice, format: VkFormat, thetype: VkImageType, tiling: VkImageTiling, usage: VkImageUsageFlags, flags: VkImageCreateFlags, externalHandleType: VkExternalMemoryHandleTypeFlagsNV, pExternalImageFormatProperties: ptr VkExternalImageFormatPropertiesNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV")) - -# extension VK_NV_optical_flow -var - vkGetPhysicalDeviceOpticalFlowImageFormatsNV*: proc(physicalDevice: VkPhysicalDevice, pOpticalFlowImageFormatInfo: ptr VkOpticalFlowImageFormatInfoNV, pFormatCount: ptr uint32, pImageFormatProperties: ptr VkOpticalFlowImageFormatPropertiesNV): VkResult {.stdcall.} - vkCreateOpticalFlowSessionNV*: proc(device: VkDevice, pCreateInfo: ptr VkOpticalFlowSessionCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pSession: ptr VkOpticalFlowSessionNV): VkResult {.stdcall.} - vkDestroyOpticalFlowSessionNV*: proc(device: VkDevice, session: VkOpticalFlowSessionNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkBindOpticalFlowSessionImageNV*: proc(device: VkDevice, session: VkOpticalFlowSessionNV, bindingPoint: VkOpticalFlowSessionBindingPointNV, view: VkImageView, layout: VkImageLayout): VkResult {.stdcall.} - vkCmdOpticalFlowExecuteNV*: proc(commandBuffer: VkCommandBuffer, session: VkOpticalFlowSessionNV, pExecuteInfo: ptr VkOpticalFlowExecuteInfoNV): void {.stdcall.} -proc loadVK_NV_optical_flow*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_3(instance) - loadVK_VERSION_1_3(instance) - vkGetPhysicalDeviceOpticalFlowImageFormatsNV = cast[proc(physicalDevice: VkPhysicalDevice, pOpticalFlowImageFormatInfo: ptr VkOpticalFlowImageFormatInfoNV, pFormatCount: ptr uint32, pImageFormatProperties: ptr VkOpticalFlowImageFormatPropertiesNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceOpticalFlowImageFormatsNV")) - vkCreateOpticalFlowSessionNV = cast[proc(device: VkDevice, pCreateInfo: ptr VkOpticalFlowSessionCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pSession: ptr VkOpticalFlowSessionNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateOpticalFlowSessionNV")) - vkDestroyOpticalFlowSessionNV = cast[proc(device: VkDevice, session: VkOpticalFlowSessionNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyOpticalFlowSessionNV")) - vkBindOpticalFlowSessionImageNV = cast[proc(device: VkDevice, session: VkOpticalFlowSessionNV, bindingPoint: VkOpticalFlowSessionBindingPointNV, view: VkImageView, layout: VkImageLayout): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindOpticalFlowSessionImageNV")) - vkCmdOpticalFlowExecuteNV = cast[proc(commandBuffer: VkCommandBuffer, session: VkOpticalFlowSessionNV, pExecuteInfo: ptr VkOpticalFlowExecuteInfoNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdOpticalFlowExecuteNV")) - -proc loadVK_EXT_vertex_attribute_divisor*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_EXT_line_rasterization -var - vkCmdSetLineStippleEXT*: proc(commandBuffer: VkCommandBuffer, lineStippleFactor: uint32, lineStipplePattern: uint16): void {.stdcall.} -proc loadVK_EXT_line_rasterization*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdSetLineStippleEXT = cast[proc(commandBuffer: VkCommandBuffer, lineStippleFactor: uint32, lineStipplePattern: uint16): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetLineStippleEXT")) - -proc loadVK_AMD_texture_gather_bias_lod*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_KHR_shader_subgroup_uniform_control_flow*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_external_memory_dma_buf*(instance: VkInstance) = - loadVK_KHR_external_memory_fd(instance) - -proc loadVK_IMG_filter_cubic*(instance: VkInstance) = - discard - -proc loadVK_AMD_shader_ballot*(instance: VkInstance) = - discard - -# extension VK_AMD_buffer_marker -var - vkCmdWriteBufferMarkerAMD*: proc(commandBuffer: VkCommandBuffer, pipelineStage: VkPipelineStageFlagBits, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, marker: uint32): void {.stdcall.} -proc loadVK_AMD_buffer_marker*(instance: VkInstance) = - vkCmdWriteBufferMarkerAMD = cast[proc(commandBuffer: VkCommandBuffer, pipelineStage: VkPipelineStageFlagBits, dstBuffer: VkBuffer, dstOffset: VkDeviceSize, marker: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteBufferMarkerAMD")) - -proc loadVK_NV_corner_sampled_image*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_KHR_pipeline_library*(instance: VkInstance) = - discard - -proc loadVK_EXT_blend_operation_advanced*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_NV_scissor_exclusive -var - vkCmdSetExclusiveScissorEnableNV*: proc(commandBuffer: VkCommandBuffer, firstExclusiveScissor: uint32, exclusiveScissorCount: uint32, pExclusiveScissorEnables: ptr VkBool32): void {.stdcall.} - vkCmdSetExclusiveScissorNV*: proc(commandBuffer: VkCommandBuffer, firstExclusiveScissor: uint32, exclusiveScissorCount: uint32, pExclusiveScissors: ptr VkRect2D): void {.stdcall.} -proc loadVK_NV_scissor_exclusive*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdSetExclusiveScissorEnableNV = cast[proc(commandBuffer: VkCommandBuffer, firstExclusiveScissor: uint32, exclusiveScissorCount: uint32, pExclusiveScissorEnables: ptr VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetExclusiveScissorEnableNV")) - vkCmdSetExclusiveScissorNV = cast[proc(commandBuffer: VkCommandBuffer, firstExclusiveScissor: uint32, exclusiveScissorCount: uint32, pExclusiveScissors: ptr VkRect2D): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetExclusiveScissorNV")) - -proc loadVK_NV_framebuffer_mixed_samples*(instance: VkInstance) = - discard - -proc loadVK_NV_sample_mask_override_coverage*(instance: VkInstance) = - discard - -proc loadVK_EXT_filter_cubic*(instance: VkInstance) = - discard - -# extension VK_KHR_pipeline_executable_properties -var - vkGetPipelineExecutablePropertiesKHR*: proc(device: VkDevice, pPipelineInfo: ptr VkPipelineInfoKHR, pExecutableCount: ptr uint32, pProperties: ptr VkPipelineExecutablePropertiesKHR): VkResult {.stdcall.} - vkGetPipelineExecutableStatisticsKHR*: proc(device: VkDevice, pExecutableInfo: ptr VkPipelineExecutableInfoKHR, pStatisticCount: ptr uint32, pStatistics: ptr VkPipelineExecutableStatisticKHR): VkResult {.stdcall.} - vkGetPipelineExecutableInternalRepresentationsKHR*: proc(device: VkDevice, pExecutableInfo: ptr VkPipelineExecutableInfoKHR, pInternalRepresentationCount: ptr uint32, pInternalRepresentations: ptr VkPipelineExecutableInternalRepresentationKHR): VkResult {.stdcall.} -proc loadVK_KHR_pipeline_executable_properties*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetPipelineExecutablePropertiesKHR = cast[proc(device: VkDevice, pPipelineInfo: ptr VkPipelineInfoKHR, pExecutableCount: ptr uint32, pProperties: ptr VkPipelineExecutablePropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPipelineExecutablePropertiesKHR")) - vkGetPipelineExecutableStatisticsKHR = cast[proc(device: VkDevice, pExecutableInfo: ptr VkPipelineExecutableInfoKHR, pStatisticCount: ptr uint32, pStatistics: ptr VkPipelineExecutableStatisticKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPipelineExecutableStatisticsKHR")) - vkGetPipelineExecutableInternalRepresentationsKHR = cast[proc(device: VkDevice, pExecutableInfo: ptr VkPipelineExecutableInfoKHR, pInternalRepresentationCount: ptr uint32, pInternalRepresentations: ptr VkPipelineExecutableInternalRepresentationKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPipelineExecutableInternalRepresentationsKHR")) - -# extension VK_EXT_extended_dynamic_state3 -var - vkCmdSetTessellationDomainOriginEXT*: proc(commandBuffer: VkCommandBuffer, domainOrigin: VkTessellationDomainOrigin): void {.stdcall.} - vkCmdSetDepthClampEnableEXT*: proc(commandBuffer: VkCommandBuffer, depthClampEnable: VkBool32): void {.stdcall.} - vkCmdSetPolygonModeEXT*: proc(commandBuffer: VkCommandBuffer, polygonMode: VkPolygonMode): void {.stdcall.} - vkCmdSetRasterizationSamplesEXT*: proc(commandBuffer: VkCommandBuffer, rasterizationSamples: VkSampleCountFlagBits): void {.stdcall.} - vkCmdSetSampleMaskEXT*: proc(commandBuffer: VkCommandBuffer, samples: VkSampleCountFlagBits, pSampleMask: ptr VkSampleMask): void {.stdcall.} - vkCmdSetAlphaToCoverageEnableEXT*: proc(commandBuffer: VkCommandBuffer, alphaToCoverageEnable: VkBool32): void {.stdcall.} - vkCmdSetAlphaToOneEnableEXT*: proc(commandBuffer: VkCommandBuffer, alphaToOneEnable: VkBool32): void {.stdcall.} - vkCmdSetLogicOpEnableEXT*: proc(commandBuffer: VkCommandBuffer, logicOpEnable: VkBool32): void {.stdcall.} - vkCmdSetColorBlendEnableEXT*: proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendEnables: ptr VkBool32): void {.stdcall.} - vkCmdSetColorBlendEquationEXT*: proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendEquations: ptr VkColorBlendEquationEXT): void {.stdcall.} - vkCmdSetColorWriteMaskEXT*: proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorWriteMasks: ptr VkColorComponentFlags): void {.stdcall.} - vkCmdSetRasterizationStreamEXT*: proc(commandBuffer: VkCommandBuffer, rasterizationStream: uint32): void {.stdcall.} - vkCmdSetConservativeRasterizationModeEXT*: proc(commandBuffer: VkCommandBuffer, conservativeRasterizationMode: VkConservativeRasterizationModeEXT): void {.stdcall.} - vkCmdSetExtraPrimitiveOverestimationSizeEXT*: proc(commandBuffer: VkCommandBuffer, extraPrimitiveOverestimationSize: float32): void {.stdcall.} - vkCmdSetDepthClipEnableEXT*: proc(commandBuffer: VkCommandBuffer, depthClipEnable: VkBool32): void {.stdcall.} - vkCmdSetSampleLocationsEnableEXT*: proc(commandBuffer: VkCommandBuffer, sampleLocationsEnable: VkBool32): void {.stdcall.} - vkCmdSetColorBlendAdvancedEXT*: proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendAdvanced: ptr VkColorBlendAdvancedEXT): void {.stdcall.} - vkCmdSetProvokingVertexModeEXT*: proc(commandBuffer: VkCommandBuffer, provokingVertexMode: VkProvokingVertexModeEXT): void {.stdcall.} - vkCmdSetLineRasterizationModeEXT*: proc(commandBuffer: VkCommandBuffer, lineRasterizationMode: VkLineRasterizationModeEXT): void {.stdcall.} - vkCmdSetLineStippleEnableEXT*: proc(commandBuffer: VkCommandBuffer, stippledLineEnable: VkBool32): void {.stdcall.} - vkCmdSetDepthClipNegativeOneToOneEXT*: proc(commandBuffer: VkCommandBuffer, negativeOneToOne: VkBool32): void {.stdcall.} - vkCmdSetViewportWScalingEnableNV*: proc(commandBuffer: VkCommandBuffer, viewportWScalingEnable: VkBool32): void {.stdcall.} - vkCmdSetViewportSwizzleNV*: proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewportSwizzles: ptr VkViewportSwizzleNV): void {.stdcall.} - vkCmdSetCoverageToColorEnableNV*: proc(commandBuffer: VkCommandBuffer, coverageToColorEnable: VkBool32): void {.stdcall.} - vkCmdSetCoverageToColorLocationNV*: proc(commandBuffer: VkCommandBuffer, coverageToColorLocation: uint32): void {.stdcall.} - vkCmdSetCoverageModulationModeNV*: proc(commandBuffer: VkCommandBuffer, coverageModulationMode: VkCoverageModulationModeNV): void {.stdcall.} - vkCmdSetCoverageModulationTableEnableNV*: proc(commandBuffer: VkCommandBuffer, coverageModulationTableEnable: VkBool32): void {.stdcall.} - vkCmdSetCoverageModulationTableNV*: proc(commandBuffer: VkCommandBuffer, coverageModulationTableCount: uint32, pCoverageModulationTable: ptr float32): void {.stdcall.} - vkCmdSetShadingRateImageEnableNV*: proc(commandBuffer: VkCommandBuffer, shadingRateImageEnable: VkBool32): void {.stdcall.} - vkCmdSetRepresentativeFragmentTestEnableNV*: proc(commandBuffer: VkCommandBuffer, representativeFragmentTestEnable: VkBool32): void {.stdcall.} - vkCmdSetCoverageReductionModeNV*: proc(commandBuffer: VkCommandBuffer, coverageReductionMode: VkCoverageReductionModeNV): void {.stdcall.} -proc loadVK_EXT_extended_dynamic_state3*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdSetTessellationDomainOriginEXT = cast[proc(commandBuffer: VkCommandBuffer, domainOrigin: VkTessellationDomainOrigin): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetTessellationDomainOriginEXT")) - vkCmdSetDepthClampEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, depthClampEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthClampEnableEXT")) - vkCmdSetPolygonModeEXT = cast[proc(commandBuffer: VkCommandBuffer, polygonMode: VkPolygonMode): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPolygonModeEXT")) - vkCmdSetRasterizationSamplesEXT = cast[proc(commandBuffer: VkCommandBuffer, rasterizationSamples: VkSampleCountFlagBits): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetRasterizationSamplesEXT")) - vkCmdSetSampleMaskEXT = cast[proc(commandBuffer: VkCommandBuffer, samples: VkSampleCountFlagBits, pSampleMask: ptr VkSampleMask): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetSampleMaskEXT")) - vkCmdSetAlphaToCoverageEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, alphaToCoverageEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetAlphaToCoverageEnableEXT")) - vkCmdSetAlphaToOneEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, alphaToOneEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetAlphaToOneEnableEXT")) - vkCmdSetLogicOpEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, logicOpEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetLogicOpEnableEXT")) - vkCmdSetColorBlendEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendEnables: ptr VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetColorBlendEnableEXT")) - vkCmdSetColorBlendEquationEXT = cast[proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendEquations: ptr VkColorBlendEquationEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetColorBlendEquationEXT")) - vkCmdSetColorWriteMaskEXT = cast[proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorWriteMasks: ptr VkColorComponentFlags): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetColorWriteMaskEXT")) - vkCmdSetRasterizationStreamEXT = cast[proc(commandBuffer: VkCommandBuffer, rasterizationStream: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetRasterizationStreamEXT")) - vkCmdSetConservativeRasterizationModeEXT = cast[proc(commandBuffer: VkCommandBuffer, conservativeRasterizationMode: VkConservativeRasterizationModeEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetConservativeRasterizationModeEXT")) - vkCmdSetExtraPrimitiveOverestimationSizeEXT = cast[proc(commandBuffer: VkCommandBuffer, extraPrimitiveOverestimationSize: float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetExtraPrimitiveOverestimationSizeEXT")) - vkCmdSetDepthClipEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, depthClipEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthClipEnableEXT")) - vkCmdSetSampleLocationsEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, sampleLocationsEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetSampleLocationsEnableEXT")) - vkCmdSetColorBlendAdvancedEXT = cast[proc(commandBuffer: VkCommandBuffer, firstAttachment: uint32, attachmentCount: uint32, pColorBlendAdvanced: ptr VkColorBlendAdvancedEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetColorBlendAdvancedEXT")) - vkCmdSetProvokingVertexModeEXT = cast[proc(commandBuffer: VkCommandBuffer, provokingVertexMode: VkProvokingVertexModeEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetProvokingVertexModeEXT")) - vkCmdSetLineRasterizationModeEXT = cast[proc(commandBuffer: VkCommandBuffer, lineRasterizationMode: VkLineRasterizationModeEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetLineRasterizationModeEXT")) - vkCmdSetLineStippleEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, stippledLineEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetLineStippleEnableEXT")) - vkCmdSetDepthClipNegativeOneToOneEXT = cast[proc(commandBuffer: VkCommandBuffer, negativeOneToOne: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDepthClipNegativeOneToOneEXT")) - vkCmdSetViewportWScalingEnableNV = cast[proc(commandBuffer: VkCommandBuffer, viewportWScalingEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewportWScalingEnableNV")) - vkCmdSetViewportSwizzleNV = cast[proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewportSwizzles: ptr VkViewportSwizzleNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewportSwizzleNV")) - vkCmdSetCoverageToColorEnableNV = cast[proc(commandBuffer: VkCommandBuffer, coverageToColorEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageToColorEnableNV")) - vkCmdSetCoverageToColorLocationNV = cast[proc(commandBuffer: VkCommandBuffer, coverageToColorLocation: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageToColorLocationNV")) - vkCmdSetCoverageModulationModeNV = cast[proc(commandBuffer: VkCommandBuffer, coverageModulationMode: VkCoverageModulationModeNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageModulationModeNV")) - vkCmdSetCoverageModulationTableEnableNV = cast[proc(commandBuffer: VkCommandBuffer, coverageModulationTableEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageModulationTableEnableNV")) - vkCmdSetCoverageModulationTableNV = cast[proc(commandBuffer: VkCommandBuffer, coverageModulationTableCount: uint32, pCoverageModulationTable: ptr float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageModulationTableNV")) - vkCmdSetShadingRateImageEnableNV = cast[proc(commandBuffer: VkCommandBuffer, shadingRateImageEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetShadingRateImageEnableNV")) - vkCmdSetRepresentativeFragmentTestEnableNV = cast[proc(commandBuffer: VkCommandBuffer, representativeFragmentTestEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetRepresentativeFragmentTestEnableNV")) - vkCmdSetCoverageReductionModeNV = cast[proc(commandBuffer: VkCommandBuffer, coverageReductionMode: VkCoverageReductionModeNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetCoverageReductionModeNV")) - -proc loadVK_EXT_device_address_binding_report*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_EXT_debug_utils(instance) - -# extension VK_NV_clip_space_w_scaling -var - vkCmdSetViewportWScalingNV*: proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewportWScalings: ptr VkViewportWScalingNV): void {.stdcall.} -proc loadVK_NV_clip_space_w_scaling*(instance: VkInstance) = - vkCmdSetViewportWScalingNV = cast[proc(commandBuffer: VkCommandBuffer, firstViewport: uint32, viewportCount: uint32, pViewportWScalings: ptr VkViewportWScalingNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetViewportWScalingNV")) - -proc loadVK_NV_fill_rectangle*(instance: VkInstance) = - discard - -proc loadVK_EXT_shader_image_atomic_int64*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_ycbcr_image_arrays*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_EXT_calibrated_timestamps -var - vkGetPhysicalDeviceCalibrateableTimeDomainsEXT*: proc(physicalDevice: VkPhysicalDevice, pTimeDomainCount: ptr uint32, pTimeDomains: ptr VkTimeDomainEXT): VkResult {.stdcall.} - vkGetCalibratedTimestampsEXT*: proc(device: VkDevice, timestampCount: uint32, pTimestampInfos: ptr VkCalibratedTimestampInfoEXT, pTimestamps: ptr uint64, pMaxDeviation: ptr uint64): VkResult {.stdcall.} -proc loadVK_EXT_calibrated_timestamps*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetPhysicalDeviceCalibrateableTimeDomainsEXT = cast[proc(physicalDevice: VkPhysicalDevice, pTimeDomainCount: ptr uint32, pTimeDomains: ptr VkTimeDomainEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT")) - vkGetCalibratedTimestampsEXT = cast[proc(device: VkDevice, timestampCount: uint32, pTimestampInfos: ptr VkCalibratedTimestampInfoEXT, pTimestamps: ptr uint64, pMaxDeviation: ptr uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetCalibratedTimestampsEXT")) - -proc loadVK_EXT_attachment_feedback_loop_layout*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_AMD_mixed_attachment_samples*(instance: VkInstance) = - discard - -# extension VK_EXT_external_memory_host -var - vkGetMemoryHostPointerPropertiesEXT*: proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, pHostPointer: pointer, pMemoryHostPointerProperties: ptr VkMemoryHostPointerPropertiesEXT): VkResult {.stdcall.} -proc loadVK_EXT_external_memory_host*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetMemoryHostPointerPropertiesEXT = cast[proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, pHostPointer: pointer, pMemoryHostPointerProperties: ptr VkMemoryHostPointerPropertiesEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryHostPointerPropertiesEXT")) - -proc loadVK_ARM_shader_core_properties*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_EXT_shader_module_identifier -var - vkGetShaderModuleIdentifierEXT*: proc(device: VkDevice, shaderModule: VkShaderModule, pIdentifier: ptr VkShaderModuleIdentifierEXT): void {.stdcall.} - vkGetShaderModuleCreateInfoIdentifierEXT*: proc(device: VkDevice, pCreateInfo: ptr VkShaderModuleCreateInfo, pIdentifier: ptr VkShaderModuleIdentifierEXT): void {.stdcall.} -proc loadVK_EXT_shader_module_identifier*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_3(instance) - vkGetShaderModuleIdentifierEXT = cast[proc(device: VkDevice, shaderModule: VkShaderModule, pIdentifier: ptr VkShaderModuleIdentifierEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetShaderModuleIdentifierEXT")) - vkGetShaderModuleCreateInfoIdentifierEXT = cast[proc(device: VkDevice, pCreateInfo: ptr VkShaderModuleCreateInfo, pIdentifier: ptr VkShaderModuleIdentifierEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetShaderModuleCreateInfoIdentifierEXT")) - -proc loadVK_EXT_border_color_swizzle*(instance: VkInstance) = - loadVK_EXT_custom_border_color(instance) - -# extension VK_NV_memory_decompression -var - vkCmdDecompressMemoryNV*: proc(commandBuffer: VkCommandBuffer, decompressRegionCount: uint32, pDecompressMemoryRegions: ptr VkDecompressMemoryRegionNV): void {.stdcall.} - vkCmdDecompressMemoryIndirectCountNV*: proc(commandBuffer: VkCommandBuffer, indirectCommandsAddress: VkDeviceAddress, indirectCommandsCountAddress: VkDeviceAddress, stride: uint32): void {.stdcall.} -proc loadVK_NV_memory_decompression*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_2(instance) - vkCmdDecompressMemoryNV = cast[proc(commandBuffer: VkCommandBuffer, decompressRegionCount: uint32, pDecompressMemoryRegions: ptr VkDecompressMemoryRegionNV): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDecompressMemoryNV")) - vkCmdDecompressMemoryIndirectCountNV = cast[proc(commandBuffer: VkCommandBuffer, indirectCommandsAddress: VkDeviceAddress, indirectCommandsCountAddress: VkDeviceAddress, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDecompressMemoryIndirectCountNV")) - -proc loadVK_EXT_fragment_shader_interlock*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_NV_coverage_reduction_mode -var - vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV*: proc(physicalDevice: VkPhysicalDevice, pCombinationCount: ptr uint32, pCombinations: ptr VkFramebufferMixedSamplesCombinationNV): VkResult {.stdcall.} -proc loadVK_NV_coverage_reduction_mode*(instance: VkInstance) = - loadVK_NV_framebuffer_mixed_samples(instance) - loadVK_VERSION_1_1(instance) - vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = cast[proc(physicalDevice: VkPhysicalDevice, pCombinationCount: ptr uint32, pCombinations: ptr VkFramebufferMixedSamplesCombinationNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV")) - -proc loadVK_NV_glsl_shader*(instance: VkInstance) = - discard - -proc loadVK_KHR_shader_clock*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_QCOM_tile_properties -var - vkGetFramebufferTilePropertiesQCOM*: proc(device: VkDevice, framebuffer: VkFramebuffer, pPropertiesCount: ptr uint32, pProperties: ptr VkTilePropertiesQCOM): VkResult {.stdcall.} - vkGetDynamicRenderingTilePropertiesQCOM*: proc(device: VkDevice, pRenderingInfo: ptr VkRenderingInfo, pProperties: ptr VkTilePropertiesQCOM): VkResult {.stdcall.} -proc loadVK_QCOM_tile_properties*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetFramebufferTilePropertiesQCOM = cast[proc(device: VkDevice, framebuffer: VkFramebuffer, pPropertiesCount: ptr uint32, pProperties: ptr VkTilePropertiesQCOM): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetFramebufferTilePropertiesQCOM")) - vkGetDynamicRenderingTilePropertiesQCOM = cast[proc(device: VkDevice, pRenderingInfo: ptr VkRenderingInfo, pProperties: ptr VkTilePropertiesQCOM): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDynamicRenderingTilePropertiesQCOM")) - -# extension VK_KHR_push_descriptor -var - vkCmdPushDescriptorSetKHR*: proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, set: uint32, descriptorWriteCount: uint32, pDescriptorWrites: ptr VkWriteDescriptorSet): void {.stdcall.} - vkCmdPushDescriptorSetWithTemplateKHR*: proc(commandBuffer: VkCommandBuffer, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, layout: VkPipelineLayout, set: uint32, pData: pointer): void {.stdcall.} -proc loadVK_KHR_push_descriptor*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdPushDescriptorSetKHR = cast[proc(commandBuffer: VkCommandBuffer, pipelineBindPoint: VkPipelineBindPoint, layout: VkPipelineLayout, set: uint32, descriptorWriteCount: uint32, pDescriptorWrites: ptr VkWriteDescriptorSet): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPushDescriptorSetKHR")) - vkCmdPushDescriptorSetWithTemplateKHR = cast[proc(commandBuffer: VkCommandBuffer, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, layout: VkPipelineLayout, set: uint32, pData: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPushDescriptorSetWithTemplateKHR")) - vkCmdPushDescriptorSetWithTemplateKHR = cast[proc(commandBuffer: VkCommandBuffer, descriptorUpdateTemplate: VkDescriptorUpdateTemplate, layout: VkPipelineLayout, set: uint32, pData: pointer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdPushDescriptorSetWithTemplateKHR")) - -proc loadVK_NV_viewport_swizzle*(instance: VkInstance) = - discard - -proc loadVK_NV_external_memory*(instance: VkInstance) = - loadVK_NV_external_memory_capabilities(instance) - -proc loadVK_EXT_depth_clip_control*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_validation_flags*(instance: VkInstance) = - discard - -proc loadVK_EXT_conservative_rasterization*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_AMD_gcn_shader*(instance: VkInstance) = - discard - -# extension VK_INTEL_performance_query -var - vkInitializePerformanceApiINTEL*: proc(device: VkDevice, pInitializeInfo: ptr VkInitializePerformanceApiInfoINTEL): VkResult {.stdcall.} - vkUninitializePerformanceApiINTEL*: proc(device: VkDevice): void {.stdcall.} - vkCmdSetPerformanceMarkerINTEL*: proc(commandBuffer: VkCommandBuffer, pMarkerInfo: ptr VkPerformanceMarkerInfoINTEL): VkResult {.stdcall.} - vkCmdSetPerformanceStreamMarkerINTEL*: proc(commandBuffer: VkCommandBuffer, pMarkerInfo: ptr VkPerformanceStreamMarkerInfoINTEL): VkResult {.stdcall.} - vkCmdSetPerformanceOverrideINTEL*: proc(commandBuffer: VkCommandBuffer, pOverrideInfo: ptr VkPerformanceOverrideInfoINTEL): VkResult {.stdcall.} - vkAcquirePerformanceConfigurationINTEL*: proc(device: VkDevice, pAcquireInfo: ptr VkPerformanceConfigurationAcquireInfoINTEL, pConfiguration: ptr VkPerformanceConfigurationINTEL): VkResult {.stdcall.} - vkReleasePerformanceConfigurationINTEL*: proc(device: VkDevice, configuration: VkPerformanceConfigurationINTEL): VkResult {.stdcall.} - vkQueueSetPerformanceConfigurationINTEL*: proc(queue: VkQueue, configuration: VkPerformanceConfigurationINTEL): VkResult {.stdcall.} - vkGetPerformanceParameterINTEL*: proc(device: VkDevice, parameter: VkPerformanceParameterTypeINTEL, pValue: ptr VkPerformanceValueINTEL): VkResult {.stdcall.} -proc loadVK_INTEL_performance_query*(instance: VkInstance) = - vkInitializePerformanceApiINTEL = cast[proc(device: VkDevice, pInitializeInfo: ptr VkInitializePerformanceApiInfoINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkInitializePerformanceApiINTEL")) - vkUninitializePerformanceApiINTEL = cast[proc(device: VkDevice): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkUninitializePerformanceApiINTEL")) - vkCmdSetPerformanceMarkerINTEL = cast[proc(commandBuffer: VkCommandBuffer, pMarkerInfo: ptr VkPerformanceMarkerInfoINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPerformanceMarkerINTEL")) - vkCmdSetPerformanceStreamMarkerINTEL = cast[proc(commandBuffer: VkCommandBuffer, pMarkerInfo: ptr VkPerformanceStreamMarkerInfoINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPerformanceStreamMarkerINTEL")) - vkCmdSetPerformanceOverrideINTEL = cast[proc(commandBuffer: VkCommandBuffer, pOverrideInfo: ptr VkPerformanceOverrideInfoINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetPerformanceOverrideINTEL")) - vkAcquirePerformanceConfigurationINTEL = cast[proc(device: VkDevice, pAcquireInfo: ptr VkPerformanceConfigurationAcquireInfoINTEL, pConfiguration: ptr VkPerformanceConfigurationINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquirePerformanceConfigurationINTEL")) - vkReleasePerformanceConfigurationINTEL = cast[proc(device: VkDevice, configuration: VkPerformanceConfigurationINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkReleasePerformanceConfigurationINTEL")) - vkQueueSetPerformanceConfigurationINTEL = cast[proc(queue: VkQueue, configuration: VkPerformanceConfigurationINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueueSetPerformanceConfigurationINTEL")) - vkGetPerformanceParameterINTEL = cast[proc(device: VkDevice, parameter: VkPerformanceParameterTypeINTEL, pValue: ptr VkPerformanceValueINTEL): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPerformanceParameterINTEL")) - -proc loadVK_EXT_primitives_generated_query*(instance: VkInstance) = - loadVK_EXT_transform_feedback(instance) - -proc loadVK_AMD_pipeline_compiler_control*(instance: VkInstance) = - discard - -proc loadVK_EXT_post_depth_coverage*(instance: VkInstance) = - discard - -# extension VK_EXT_conditional_rendering -var - vkCmdBeginConditionalRenderingEXT*: proc(commandBuffer: VkCommandBuffer, pConditionalRenderingBegin: ptr VkConditionalRenderingBeginInfoEXT): void {.stdcall.} - vkCmdEndConditionalRenderingEXT*: proc(commandBuffer: VkCommandBuffer): void {.stdcall.} -proc loadVK_EXT_conditional_rendering*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdBeginConditionalRenderingEXT = cast[proc(commandBuffer: VkCommandBuffer, pConditionalRenderingBegin: ptr VkConditionalRenderingBeginInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginConditionalRenderingEXT")) - vkCmdEndConditionalRenderingEXT = cast[proc(commandBuffer: VkCommandBuffer): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndConditionalRenderingEXT")) - -proc loadVK_QCOM_multiview_per_view_viewports*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_EXT_multi_draw -var - vkCmdDrawMultiEXT*: proc(commandBuffer: VkCommandBuffer, drawCount: uint32, pVertexInfo: ptr VkMultiDrawInfoEXT, instanceCount: uint32, firstInstance: uint32, stride: uint32): void {.stdcall.} - vkCmdDrawMultiIndexedEXT*: proc(commandBuffer: VkCommandBuffer, drawCount: uint32, pIndexInfo: ptr VkMultiDrawIndexedInfoEXT, instanceCount: uint32, firstInstance: uint32, stride: uint32, pVertexOffset: ptr int32): void {.stdcall.} -proc loadVK_EXT_multi_draw*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdDrawMultiEXT = cast[proc(commandBuffer: VkCommandBuffer, drawCount: uint32, pVertexInfo: ptr VkMultiDrawInfoEXT, instanceCount: uint32, firstInstance: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMultiEXT")) - vkCmdDrawMultiIndexedEXT = cast[proc(commandBuffer: VkCommandBuffer, drawCount: uint32, pIndexInfo: ptr VkMultiDrawIndexedInfoEXT, instanceCount: uint32, firstInstance: uint32, stride: uint32, pVertexOffset: ptr int32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawMultiIndexedEXT")) - -proc loadVK_NV_fragment_coverage_to_color*(instance: VkInstance) = - discard - -proc loadVK_EXT_load_store_op_none*(instance: VkInstance) = - discard - -proc loadVK_EXT_validation_features*(instance: VkInstance) = - discard - -proc loadVK_KHR_workgroup_memory_explicit_layout*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_index_type_uint8*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_GOOGLE_decorate_string*(instance: VkInstance) = - discard - -proc loadVK_EXT_shader_atomic_float*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_EXT_pipeline_properties -var - vkGetPipelinePropertiesEXT*: proc(device: VkDevice, pPipelineInfo: ptr VkPipelineInfoEXT, pPipelineProperties: ptr VkBaseOutStructure): VkResult {.stdcall.} -proc loadVK_EXT_pipeline_properties*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetPipelinePropertiesEXT = cast[proc(device: VkDevice, pPipelineInfo: ptr VkPipelineInfoEXT, pPipelineProperties: ptr VkBaseOutStructure): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPipelinePropertiesEXT")) - -proc loadVK_EXT_graphics_pipeline_library*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_KHR_pipeline_library(instance) - -# extension VK_KHR_surface -var - vkDestroySurfaceKHR*: proc(instance: VkInstance, surface: VkSurfaceKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetPhysicalDeviceSurfaceSupportKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, surface: VkSurfaceKHR, pSupported: ptr VkBool32): VkResult {.stdcall.} - vkGetPhysicalDeviceSurfaceCapabilitiesKHR*: proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceCapabilities: ptr VkSurfaceCapabilitiesKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceSurfaceFormatsKHR*: proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceFormatCount: ptr uint32, pSurfaceFormats: ptr VkSurfaceFormatKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceSurfacePresentModesKHR*: proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pPresentModeCount: ptr uint32, pPresentModes: ptr VkPresentModeKHR): VkResult {.stdcall.} -proc loadVK_KHR_surface*(instance: VkInstance) = - vkDestroySurfaceKHR = cast[proc(instance: VkInstance, surface: VkSurfaceKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR")) - vkGetPhysicalDeviceSurfaceSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, surface: VkSurfaceKHR, pSupported: ptr VkBool32): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR")) - vkGetPhysicalDeviceSurfaceCapabilitiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceCapabilities: ptr VkSurfaceCapabilitiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR")) - vkGetPhysicalDeviceSurfaceFormatsKHR = cast[proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceFormatCount: ptr uint32, pSurfaceFormats: ptr VkSurfaceFormatKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR")) - vkGetPhysicalDeviceSurfacePresentModesKHR = cast[proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pPresentModeCount: ptr uint32, pPresentModes: ptr VkPresentModeKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR")) - -proc loadVK_AMD_gpu_shader_half_float*(instance: VkInstance) = - discard - -# extension VK_KHR_deferred_host_operations -var - vkCreateDeferredOperationKHR*: proc(device: VkDevice, pAllocator: ptr VkAllocationCallbacks, pDeferredOperation: ptr VkDeferredOperationKHR): VkResult {.stdcall.} - vkDestroyDeferredOperationKHR*: proc(device: VkDevice, operation: VkDeferredOperationKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetDeferredOperationMaxConcurrencyKHR*: proc(device: VkDevice, operation: VkDeferredOperationKHR): uint32 {.stdcall.} - vkGetDeferredOperationResultKHR*: proc(device: VkDevice, operation: VkDeferredOperationKHR): VkResult {.stdcall.} - vkDeferredOperationJoinKHR*: proc(device: VkDevice, operation: VkDeferredOperationKHR): VkResult {.stdcall.} -proc loadVK_KHR_deferred_host_operations*(instance: VkInstance) = - vkCreateDeferredOperationKHR = cast[proc(device: VkDevice, pAllocator: ptr VkAllocationCallbacks, pDeferredOperation: ptr VkDeferredOperationKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDeferredOperationKHR")) - vkDestroyDeferredOperationKHR = cast[proc(device: VkDevice, operation: VkDeferredOperationKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyDeferredOperationKHR")) - vkGetDeferredOperationMaxConcurrencyKHR = cast[proc(device: VkDevice, operation: VkDeferredOperationKHR): uint32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeferredOperationMaxConcurrencyKHR")) - vkGetDeferredOperationResultKHR = cast[proc(device: VkDevice, operation: VkDeferredOperationKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeferredOperationResultKHR")) - vkDeferredOperationJoinKHR = cast[proc(device: VkDevice, operation: VkDeferredOperationKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDeferredOperationJoinKHR")) - -proc loadVK_NV_dedicated_allocation*(instance: VkInstance) = - discard - -# extension VK_NVX_image_view_handle -var - vkGetImageViewHandleNVX*: proc(device: VkDevice, pInfo: ptr VkImageViewHandleInfoNVX): uint32 {.stdcall.} - vkGetImageViewAddressNVX*: proc(device: VkDevice, imageView: VkImageView, pProperties: ptr VkImageViewAddressPropertiesNVX): VkResult {.stdcall.} -proc loadVK_NVX_image_view_handle*(instance: VkInstance) = - vkGetImageViewHandleNVX = cast[proc(device: VkDevice, pInfo: ptr VkImageViewHandleInfoNVX): uint32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageViewHandleNVX")) - vkGetImageViewAddressNVX = cast[proc(device: VkDevice, imageView: VkImageView, pProperties: ptr VkImageViewAddressPropertiesNVX): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetImageViewAddressNVX")) - -proc loadVK_EXT_non_seamless_cube_map*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_QCOM_render_pass_store_ops*(instance: VkInstance) = - discard - -# extension VK_EXT_device_fault -var - vkGetDeviceFaultInfoEXT*: proc(device: VkDevice, pFaultCounts: ptr VkDeviceFaultCountsEXT, pFaultInfo: ptr VkDeviceFaultInfoEXT): VkResult {.stdcall.} -proc loadVK_EXT_device_fault*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetDeviceFaultInfoEXT = cast[proc(device: VkDevice, pFaultCounts: ptr VkDeviceFaultCountsEXT, pFaultInfo: ptr VkDeviceFaultInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceFaultInfoEXT")) - -proc loadVK_EXT_mutable_descriptor_type*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_EXT_color_write_enable -var - vkCmdSetColorWriteEnableEXT*: proc(commandBuffer: VkCommandBuffer, attachmentCount: uint32, pColorWriteEnables: ptr VkBool32): void {.stdcall.} -proc loadVK_EXT_color_write_enable*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdSetColorWriteEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, attachmentCount: uint32, pColorWriteEnables: ptr VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetColorWriteEnableEXT")) - -proc loadVK_SEC_amigo_profiling*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_NVX_binary_import -var - vkCreateCuModuleNVX*: proc(device: VkDevice, pCreateInfo: ptr VkCuModuleCreateInfoNVX, pAllocator: ptr VkAllocationCallbacks, pModule: ptr VkCuModuleNVX): VkResult {.stdcall.} - vkCreateCuFunctionNVX*: proc(device: VkDevice, pCreateInfo: ptr VkCuFunctionCreateInfoNVX, pAllocator: ptr VkAllocationCallbacks, pFunction: ptr VkCuFunctionNVX): VkResult {.stdcall.} - vkDestroyCuModuleNVX*: proc(device: VkDevice, module: VkCuModuleNVX, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkDestroyCuFunctionNVX*: proc(device: VkDevice, function: VkCuFunctionNVX, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCmdCuLaunchKernelNVX*: proc(commandBuffer: VkCommandBuffer, pLaunchInfo: ptr VkCuLaunchInfoNVX): void {.stdcall.} -proc loadVK_NVX_binary_import*(instance: VkInstance) = - vkCreateCuModuleNVX = cast[proc(device: VkDevice, pCreateInfo: ptr VkCuModuleCreateInfoNVX, pAllocator: ptr VkAllocationCallbacks, pModule: ptr VkCuModuleNVX): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateCuModuleNVX")) - vkCreateCuFunctionNVX = cast[proc(device: VkDevice, pCreateInfo: ptr VkCuFunctionCreateInfoNVX, pAllocator: ptr VkAllocationCallbacks, pFunction: ptr VkCuFunctionNVX): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateCuFunctionNVX")) - vkDestroyCuModuleNVX = cast[proc(device: VkDevice, module: VkCuModuleNVX, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyCuModuleNVX")) - vkDestroyCuFunctionNVX = cast[proc(device: VkDevice, function: VkCuFunctionNVX, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyCuFunctionNVX")) - vkCmdCuLaunchKernelNVX = cast[proc(commandBuffer: VkCommandBuffer, pLaunchInfo: ptr VkCuLaunchInfoNVX): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCuLaunchKernelNVX")) - -proc loadVK_NV_representative_fragment_test*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_EXT_validation_cache -var - vkCreateValidationCacheEXT*: proc(device: VkDevice, pCreateInfo: ptr VkValidationCacheCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pValidationCache: ptr VkValidationCacheEXT): VkResult {.stdcall.} - vkDestroyValidationCacheEXT*: proc(device: VkDevice, validationCache: VkValidationCacheEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkMergeValidationCachesEXT*: proc(device: VkDevice, dstCache: VkValidationCacheEXT, srcCacheCount: uint32, pSrcCaches: ptr VkValidationCacheEXT): VkResult {.stdcall.} - vkGetValidationCacheDataEXT*: proc(device: VkDevice, validationCache: VkValidationCacheEXT, pDataSize: ptr csize_t, pData: pointer): VkResult {.stdcall.} -proc loadVK_EXT_validation_cache*(instance: VkInstance) = - vkCreateValidationCacheEXT = cast[proc(device: VkDevice, pCreateInfo: ptr VkValidationCacheCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pValidationCache: ptr VkValidationCacheEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateValidationCacheEXT")) - vkDestroyValidationCacheEXT = cast[proc(device: VkDevice, validationCache: VkValidationCacheEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyValidationCacheEXT")) - vkMergeValidationCachesEXT = cast[proc(device: VkDevice, dstCache: VkValidationCacheEXT, srcCacheCount: uint32, pSrcCaches: ptr VkValidationCacheEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkMergeValidationCachesEXT")) - vkGetValidationCacheDataEXT = cast[proc(device: VkDevice, validationCache: VkValidationCacheEXT, pDataSize: ptr csize_t, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetValidationCacheDataEXT")) - -proc loadVK_NV_inherited_viewport_scissor*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_legacy_dithering*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_physical_device_drm*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_pipeline_protected_access*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_EXT_discard_rectangles -var - vkCmdSetDiscardRectangleEXT*: proc(commandBuffer: VkCommandBuffer, firstDiscardRectangle: uint32, discardRectangleCount: uint32, pDiscardRectangles: ptr VkRect2D): void {.stdcall.} - vkCmdSetDiscardRectangleEnableEXT*: proc(commandBuffer: VkCommandBuffer, discardRectangleEnable: VkBool32): void {.stdcall.} - vkCmdSetDiscardRectangleModeEXT*: proc(commandBuffer: VkCommandBuffer, discardRectangleMode: VkDiscardRectangleModeEXT): void {.stdcall.} -proc loadVK_EXT_discard_rectangles*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdSetDiscardRectangleEXT = cast[proc(commandBuffer: VkCommandBuffer, firstDiscardRectangle: uint32, discardRectangleCount: uint32, pDiscardRectangles: ptr VkRect2D): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDiscardRectangleEXT")) - vkCmdSetDiscardRectangleEnableEXT = cast[proc(commandBuffer: VkCommandBuffer, discardRectangleEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDiscardRectangleEnableEXT")) - vkCmdSetDiscardRectangleModeEXT = cast[proc(commandBuffer: VkCommandBuffer, discardRectangleMode: VkDiscardRectangleModeEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetDiscardRectangleModeEXT")) - -proc loadVK_EXT_shader_stencil_export*(instance: VkInstance) = - discard - -# extension VK_NV_external_memory_rdma -var - vkGetMemoryRemoteAddressNV*: proc(device: VkDevice, pMemoryGetRemoteAddressInfo: ptr VkMemoryGetRemoteAddressInfoNV, pAddress: ptr VkRemoteAddressNV): VkResult {.stdcall.} -proc loadVK_NV_external_memory_rdma*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetMemoryRemoteAddressNV = cast[proc(device: VkDevice, pMemoryGetRemoteAddressInfo: ptr VkMemoryGetRemoteAddressInfoNV, pAddress: ptr VkRemoteAddressNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryRemoteAddressNV")) - -proc loadVK_ARM_shader_core_builtins*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_QCOM_multiview_per_view_render_areas*(instance: VkInstance) = - discard - -proc loadVK_LUNARG_direct_driver_loading*(instance: VkInstance) = - discard - -proc loadVK_AMD_shader_explicit_vertex_parameter*(instance: VkInstance) = - discard - -# extension VK_EXT_headless_surface -var - vkCreateHeadlessSurfaceEXT*: proc(instance: VkInstance, pCreateInfo: ptr VkHeadlessSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} -proc loadVK_EXT_headless_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateHeadlessSurfaceEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkHeadlessSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT")) - -proc loadVK_NV_shader_sm_builtins*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_shader_subgroup_vote*(instance: VkInstance) = - discard - -# extension VK_NV_copy_memory_indirect -var - vkCmdCopyMemoryIndirectNV*: proc(commandBuffer: VkCommandBuffer, copyBufferAddress: VkDeviceAddress, copyCount: uint32, stride: uint32): void {.stdcall.} - vkCmdCopyMemoryToImageIndirectNV*: proc(commandBuffer: VkCommandBuffer, copyBufferAddress: VkDeviceAddress, copyCount: uint32, stride: uint32, dstImage: VkImage, dstImageLayout: VkImageLayout, pImageSubresources: ptr VkImageSubresourceLayers): void {.stdcall.} -proc loadVK_NV_copy_memory_indirect*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_2(instance) - vkCmdCopyMemoryIndirectNV = cast[proc(commandBuffer: VkCommandBuffer, copyBufferAddress: VkDeviceAddress, copyCount: uint32, stride: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMemoryIndirectNV")) - vkCmdCopyMemoryToImageIndirectNV = cast[proc(commandBuffer: VkCommandBuffer, copyBufferAddress: VkDeviceAddress, copyCount: uint32, stride: uint32, dstImage: VkImage, dstImageLayout: VkImageLayout, pImageSubresources: ptr VkImageSubresourceLayers): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMemoryToImageIndirectNV")) - -proc loadVK_EXT_astc_decode_mode*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -# extension VK_KHR_get_surface_capabilities2 -var - vkGetPhysicalDeviceSurfaceCapabilities2KHR*: proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pSurfaceCapabilities: ptr VkSurfaceCapabilities2KHR): VkResult {.stdcall.} - vkGetPhysicalDeviceSurfaceFormats2KHR*: proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pSurfaceFormatCount: ptr uint32, pSurfaceFormats: ptr VkSurfaceFormat2KHR): VkResult {.stdcall.} -proc loadVK_KHR_get_surface_capabilities2*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkGetPhysicalDeviceSurfaceCapabilities2KHR = cast[proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pSurfaceCapabilities: ptr VkSurfaceCapabilities2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR")) - vkGetPhysicalDeviceSurfaceFormats2KHR = cast[proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pSurfaceFormatCount: ptr uint32, pSurfaceFormats: ptr VkSurfaceFormat2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormats2KHR")) - -# extension VK_HUAWEI_cluster_culling_shader -var - vkCmdDrawClusterHUAWEI*: proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.} - vkCmdDrawClusterIndirectHUAWEI*: proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize): void {.stdcall.} -proc loadVK_HUAWEI_cluster_culling_shader*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkCmdDrawClusterHUAWEI = cast[proc(commandBuffer: VkCommandBuffer, groupCountX: uint32, groupCountY: uint32, groupCountZ: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawClusterHUAWEI")) - vkCmdDrawClusterIndirectHUAWEI = cast[proc(commandBuffer: VkCommandBuffer, buffer: VkBuffer, offset: VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDrawClusterIndirectHUAWEI")) - -proc loadVK_KHR_surface_protected_capabilities*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_KHR_get_surface_capabilities2(instance) - -proc loadVK_NV_shader_image_footprint*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_NV_compute_shader_derivatives*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_QCOM_fragment_density_map_offset*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_EXT_fragment_density_map(instance) - -proc loadVK_EXT_shader_atomic_float2*(instance: VkInstance) = - loadVK_EXT_shader_atomic_float(instance) - -# extension VK_EXT_pageable_device_local_memory -var - vkSetDeviceMemoryPriorityEXT*: proc(device: VkDevice, memory: VkDeviceMemory, priority: float32): void {.stdcall.} -proc loadVK_EXT_pageable_device_local_memory*(instance: VkInstance) = - loadVK_EXT_memory_priority(instance) - vkSetDeviceMemoryPriorityEXT = cast[proc(device: VkDevice, memory: VkDeviceMemory, priority: float32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetDeviceMemoryPriorityEXT")) - -# extension VK_KHR_swapchain -var - vkCreateSwapchainKHR*: proc(device: VkDevice, pCreateInfo: ptr VkSwapchainCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSwapchain: ptr VkSwapchainKHR): VkResult {.stdcall.} - vkDestroySwapchainKHR*: proc(device: VkDevice, swapchain: VkSwapchainKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetSwapchainImagesKHR*: proc(device: VkDevice, swapchain: VkSwapchainKHR, pSwapchainImageCount: ptr uint32, pSwapchainImages: ptr VkImage): VkResult {.stdcall.} - vkAcquireNextImageKHR*: proc(device: VkDevice, swapchain: VkSwapchainKHR, timeout: uint64, semaphore: VkSemaphore, fence: VkFence, pImageIndex: ptr uint32): VkResult {.stdcall.} - vkQueuePresentKHR*: proc(queue: VkQueue, pPresentInfo: ptr VkPresentInfoKHR): VkResult {.stdcall.} - vkGetDeviceGroupPresentCapabilitiesKHR*: proc(device: VkDevice, pDeviceGroupPresentCapabilities: ptr VkDeviceGroupPresentCapabilitiesKHR): VkResult {.stdcall.} - vkGetDeviceGroupSurfacePresentModesKHR*: proc(device: VkDevice, surface: VkSurfaceKHR, pModes: ptr VkDeviceGroupPresentModeFlagsKHR): VkResult {.stdcall.} - vkGetPhysicalDevicePresentRectanglesKHR*: proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pRectCount: ptr uint32, pRects: ptr VkRect2D): VkResult {.stdcall.} - vkAcquireNextImage2KHR*: proc(device: VkDevice, pAcquireInfo: ptr VkAcquireNextImageInfoKHR, pImageIndex: ptr uint32): VkResult {.stdcall.} -proc loadVK_KHR_swapchain*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateSwapchainKHR = cast[proc(device: VkDevice, pCreateInfo: ptr VkSwapchainCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSwapchain: ptr VkSwapchainKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateSwapchainKHR")) - vkDestroySwapchainKHR = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroySwapchainKHR")) - vkGetSwapchainImagesKHR = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, pSwapchainImageCount: ptr uint32, pSwapchainImages: ptr VkImage): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSwapchainImagesKHR")) - vkAcquireNextImageKHR = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, timeout: uint64, semaphore: VkSemaphore, fence: VkFence, pImageIndex: ptr uint32): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireNextImageKHR")) - vkQueuePresentKHR = cast[proc(queue: VkQueue, pPresentInfo: ptr VkPresentInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkQueuePresentKHR")) - vkGetDeviceGroupPresentCapabilitiesKHR = cast[proc(device: VkDevice, pDeviceGroupPresentCapabilities: ptr VkDeviceGroupPresentCapabilitiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceGroupPresentCapabilitiesKHR")) - vkGetDeviceGroupSurfacePresentModesKHR = cast[proc(device: VkDevice, surface: VkSurfaceKHR, pModes: ptr VkDeviceGroupPresentModeFlagsKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceGroupSurfacePresentModesKHR")) - vkGetPhysicalDevicePresentRectanglesKHR = cast[proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pRectCount: ptr uint32, pRects: ptr VkRect2D): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDevicePresentRectanglesKHR")) - vkAcquireNextImage2KHR = cast[proc(device: VkDevice, pAcquireInfo: ptr VkAcquireNextImageInfoKHR, pImageIndex: ptr uint32): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireNextImage2KHR")) - -proc loadVK_EXT_fragment_density_map2*(instance: VkInstance) = - loadVK_EXT_fragment_density_map(instance) - -# extension VK_NV_fragment_shading_rate_enums -var - vkCmdSetFragmentShadingRateEnumNV*: proc(commandBuffer: VkCommandBuffer, shadingRate: VkFragmentShadingRateNV, combinerOps: array[2, VkFragmentShadingRateCombinerOpKHR]): void {.stdcall.} -proc loadVK_NV_fragment_shading_rate_enums*(instance: VkInstance) = - loadVK_KHR_fragment_shading_rate(instance) - vkCmdSetFragmentShadingRateEnumNV = cast[proc(commandBuffer: VkCommandBuffer, shadingRate: VkFragmentShadingRateNV, combinerOps: array[2, VkFragmentShadingRateCombinerOpKHR]): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetFragmentShadingRateEnumNV")) - -# extension VK_AMD_display_native_hdr -var - vkSetLocalDimmingAMD*: proc(device: VkDevice, swapChain: VkSwapchainKHR, localDimmingEnable: VkBool32): void {.stdcall.} -proc loadVK_AMD_display_native_hdr*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_KHR_get_surface_capabilities2(instance) - loadVK_KHR_swapchain(instance) - vkSetLocalDimmingAMD = cast[proc(device: VkDevice, swapChain: VkSwapchainKHR, localDimmingEnable: VkBool32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetLocalDimmingAMD")) - -proc loadVK_NV_present_barrier*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_KHR_surface(instance) - loadVK_KHR_get_surface_capabilities2(instance) - loadVK_KHR_swapchain(instance) - -proc loadVK_QCOM_rotated_copy_commands*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - loadVK_VERSION_1_3(instance) - -proc loadVK_EXT_surface_maintenance1*(instance: VkInstance) = - loadVK_KHR_surface(instance) - loadVK_KHR_get_surface_capabilities2(instance) - -# extension VK_KHR_acceleration_structure -var - vkCreateAccelerationStructureKHR*: proc(device: VkDevice, pCreateInfo: ptr VkAccelerationStructureCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pAccelerationStructure: ptr VkAccelerationStructureKHR): VkResult {.stdcall.} - vkDestroyAccelerationStructureKHR*: proc(device: VkDevice, accelerationStructure: VkAccelerationStructureKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCmdBuildAccelerationStructuresKHR*: proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, ppBuildRangeInfos: ptr ptr VkAccelerationStructureBuildRangeInfoKHR): void {.stdcall.} - vkCmdBuildAccelerationStructuresIndirectKHR*: proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, pIndirectDeviceAddresses: ptr VkDeviceAddress, pIndirectStrides: ptr uint32, ppMaxPrimitiveCounts: ptr ptr uint32): void {.stdcall.} - vkBuildAccelerationStructuresKHR*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, ppBuildRangeInfos: ptr ptr VkAccelerationStructureBuildRangeInfoKHR): VkResult {.stdcall.} - vkCopyAccelerationStructureKHR*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyAccelerationStructureInfoKHR): VkResult {.stdcall.} - vkCopyAccelerationStructureToMemoryKHR*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyAccelerationStructureToMemoryInfoKHR): VkResult {.stdcall.} - vkCopyMemoryToAccelerationStructureKHR*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMemoryToAccelerationStructureInfoKHR): VkResult {.stdcall.} - vkWriteAccelerationStructuresPropertiesKHR*: proc(device: VkDevice, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureKHR, queryType: VkQueryType, dataSize: csize_t, pData: pointer, stride: csize_t): VkResult {.stdcall.} - vkCmdCopyAccelerationStructureKHR*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyAccelerationStructureInfoKHR): void {.stdcall.} - vkCmdCopyAccelerationStructureToMemoryKHR*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyAccelerationStructureToMemoryInfoKHR): void {.stdcall.} - vkCmdCopyMemoryToAccelerationStructureKHR*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMemoryToAccelerationStructureInfoKHR): void {.stdcall.} - vkGetAccelerationStructureDeviceAddressKHR*: proc(device: VkDevice, pInfo: ptr VkAccelerationStructureDeviceAddressInfoKHR): VkDeviceAddress {.stdcall.} - vkCmdWriteAccelerationStructuresPropertiesKHR*: proc(commandBuffer: VkCommandBuffer, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureKHR, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.} - vkGetDeviceAccelerationStructureCompatibilityKHR*: proc(device: VkDevice, pVersionInfo: ptr VkAccelerationStructureVersionInfoKHR, pCompatibility: ptr VkAccelerationStructureCompatibilityKHR): void {.stdcall.} - vkGetAccelerationStructureBuildSizesKHR*: proc(device: VkDevice, buildType: VkAccelerationStructureBuildTypeKHR, pBuildInfo: ptr VkAccelerationStructureBuildGeometryInfoKHR, pMaxPrimitiveCounts: ptr uint32, pSizeInfo: ptr VkAccelerationStructureBuildSizesInfoKHR): void {.stdcall.} -proc loadVK_KHR_acceleration_structure*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_2(instance) - loadVK_VERSION_1_2(instance) - loadVK_KHR_deferred_host_operations(instance) - vkCreateAccelerationStructureKHR = cast[proc(device: VkDevice, pCreateInfo: ptr VkAccelerationStructureCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pAccelerationStructure: ptr VkAccelerationStructureKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateAccelerationStructureKHR")) - vkDestroyAccelerationStructureKHR = cast[proc(device: VkDevice, accelerationStructure: VkAccelerationStructureKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyAccelerationStructureKHR")) - vkCmdBuildAccelerationStructuresKHR = cast[proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, ppBuildRangeInfos: ptr ptr VkAccelerationStructureBuildRangeInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBuildAccelerationStructuresKHR")) - vkCmdBuildAccelerationStructuresIndirectKHR = cast[proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, pIndirectDeviceAddresses: ptr VkDeviceAddress, pIndirectStrides: ptr uint32, ppMaxPrimitiveCounts: ptr ptr uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBuildAccelerationStructuresIndirectKHR")) - vkBuildAccelerationStructuresKHR = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, infoCount: uint32, pInfos: ptr VkAccelerationStructureBuildGeometryInfoKHR, ppBuildRangeInfos: ptr ptr VkAccelerationStructureBuildRangeInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBuildAccelerationStructuresKHR")) - vkCopyAccelerationStructureKHR = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyAccelerationStructureInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyAccelerationStructureKHR")) - vkCopyAccelerationStructureToMemoryKHR = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyAccelerationStructureToMemoryInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyAccelerationStructureToMemoryKHR")) - vkCopyMemoryToAccelerationStructureKHR = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMemoryToAccelerationStructureInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyMemoryToAccelerationStructureKHR")) - vkWriteAccelerationStructuresPropertiesKHR = cast[proc(device: VkDevice, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureKHR, queryType: VkQueryType, dataSize: csize_t, pData: pointer, stride: csize_t): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkWriteAccelerationStructuresPropertiesKHR")) - vkCmdCopyAccelerationStructureKHR = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyAccelerationStructureInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyAccelerationStructureKHR")) - vkCmdCopyAccelerationStructureToMemoryKHR = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyAccelerationStructureToMemoryInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyAccelerationStructureToMemoryKHR")) - vkCmdCopyMemoryToAccelerationStructureKHR = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMemoryToAccelerationStructureInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMemoryToAccelerationStructureKHR")) - vkGetAccelerationStructureDeviceAddressKHR = cast[proc(device: VkDevice, pInfo: ptr VkAccelerationStructureDeviceAddressInfoKHR): VkDeviceAddress {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureDeviceAddressKHR")) - vkCmdWriteAccelerationStructuresPropertiesKHR = cast[proc(commandBuffer: VkCommandBuffer, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureKHR, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteAccelerationStructuresPropertiesKHR")) - vkGetDeviceAccelerationStructureCompatibilityKHR = cast[proc(device: VkDevice, pVersionInfo: ptr VkAccelerationStructureVersionInfoKHR, pCompatibility: ptr VkAccelerationStructureCompatibilityKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceAccelerationStructureCompatibilityKHR")) - vkGetAccelerationStructureBuildSizesKHR = cast[proc(device: VkDevice, buildType: VkAccelerationStructureBuildTypeKHR, pBuildInfo: ptr VkAccelerationStructureBuildGeometryInfoKHR, pMaxPrimitiveCounts: ptr uint32, pSizeInfo: ptr VkAccelerationStructureBuildSizesInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureBuildSizesKHR")) - -# extension VK_GOOGLE_display_timing -var - vkGetRefreshCycleDurationGOOGLE*: proc(device: VkDevice, swapchain: VkSwapchainKHR, pDisplayTimingProperties: ptr VkRefreshCycleDurationGOOGLE): VkResult {.stdcall.} - vkGetPastPresentationTimingGOOGLE*: proc(device: VkDevice, swapchain: VkSwapchainKHR, pPresentationTimingCount: ptr uint32, pPresentationTimings: ptr VkPastPresentationTimingGOOGLE): VkResult {.stdcall.} -proc loadVK_GOOGLE_display_timing*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - vkGetRefreshCycleDurationGOOGLE = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, pDisplayTimingProperties: ptr VkRefreshCycleDurationGOOGLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRefreshCycleDurationGOOGLE")) - vkGetPastPresentationTimingGOOGLE = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, pPresentationTimingCount: ptr uint32, pPresentationTimings: ptr VkPastPresentationTimingGOOGLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPastPresentationTimingGOOGLE")) - -proc loadVK_QCOM_render_pass_transform*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - loadVK_KHR_surface(instance) - -proc loadVK_GOOGLE_surfaceless_query*(instance: VkInstance) = - loadVK_KHR_surface(instance) - -proc loadVK_EXT_image_compression_control_swapchain*(instance: VkInstance) = - loadVK_EXT_image_compression_control(instance) - -# extension VK_KHR_display -var - vkGetPhysicalDeviceDisplayPropertiesKHR*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPropertiesKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceDisplayPlanePropertiesKHR*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPlanePropertiesKHR): VkResult {.stdcall.} - vkGetDisplayPlaneSupportedDisplaysKHR*: proc(physicalDevice: VkPhysicalDevice, planeIndex: uint32, pDisplayCount: ptr uint32, pDisplays: ptr VkDisplayKHR): VkResult {.stdcall.} - vkGetDisplayModePropertiesKHR*: proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayModePropertiesKHR): VkResult {.stdcall.} - vkCreateDisplayModeKHR*: proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pCreateInfo: ptr VkDisplayModeCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pMode: ptr VkDisplayModeKHR): VkResult {.stdcall.} - vkGetDisplayPlaneCapabilitiesKHR*: proc(physicalDevice: VkPhysicalDevice, mode: VkDisplayModeKHR, planeIndex: uint32, pCapabilities: ptr VkDisplayPlaneCapabilitiesKHR): VkResult {.stdcall.} - vkCreateDisplayPlaneSurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkDisplaySurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} -proc loadVK_KHR_display*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkGetPhysicalDeviceDisplayPropertiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR")) - vkGetPhysicalDeviceDisplayPlanePropertiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPlanePropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR")) - vkGetDisplayPlaneSupportedDisplaysKHR = cast[proc(physicalDevice: VkPhysicalDevice, planeIndex: uint32, pDisplayCount: ptr uint32, pDisplays: ptr VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR")) - vkGetDisplayModePropertiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayModePropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR")) - vkCreateDisplayModeKHR = cast[proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pCreateInfo: ptr VkDisplayModeCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pMode: ptr VkDisplayModeKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDisplayModeKHR")) - vkGetDisplayPlaneCapabilitiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, mode: VkDisplayModeKHR, planeIndex: uint32, pCapabilities: ptr VkDisplayPlaneCapabilitiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR")) - vkCreateDisplayPlaneSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDisplaySurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDisplayPlaneSurfaceKHR")) - -# extension VK_EXT_swapchain_maintenance1 -var - vkReleaseSwapchainImagesEXT*: proc(device: VkDevice, pReleaseInfo: ptr VkReleaseSwapchainImagesInfoEXT): VkResult {.stdcall.} -proc loadVK_EXT_swapchain_maintenance1*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - loadVK_EXT_surface_maintenance1(instance) - loadVK_VERSION_1_1(instance) - vkReleaseSwapchainImagesEXT = cast[proc(device: VkDevice, pReleaseInfo: ptr VkReleaseSwapchainImagesInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkReleaseSwapchainImagesEXT")) - -# extension VK_EXT_direct_mode_display -var - vkReleaseDisplayEXT*: proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR): VkResult {.stdcall.} -proc loadVK_EXT_direct_mode_display*(instance: VkInstance) = - loadVK_KHR_display(instance) - vkReleaseDisplayEXT = cast[proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkReleaseDisplayEXT")) - -proc loadVK_KHR_swapchain_mutable_format*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_2(instance) - -proc loadVK_EXT_swapchain_colorspace*(instance: VkInstance) = - loadVK_KHR_surface(instance) - -# extension VK_EXT_opacity_micromap -var - vkCreateMicromapEXT*: proc(device: VkDevice, pCreateInfo: ptr VkMicromapCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pMicromap: ptr VkMicromapEXT): VkResult {.stdcall.} - vkDestroyMicromapEXT*: proc(device: VkDevice, micromap: VkMicromapEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCmdBuildMicromapsEXT*: proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkMicromapBuildInfoEXT): void {.stdcall.} - vkBuildMicromapsEXT*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, infoCount: uint32, pInfos: ptr VkMicromapBuildInfoEXT): VkResult {.stdcall.} - vkCopyMicromapEXT*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMicromapInfoEXT): VkResult {.stdcall.} - vkCopyMicromapToMemoryEXT*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMicromapToMemoryInfoEXT): VkResult {.stdcall.} - vkCopyMemoryToMicromapEXT*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMemoryToMicromapInfoEXT): VkResult {.stdcall.} - vkWriteMicromapsPropertiesEXT*: proc(device: VkDevice, micromapCount: uint32, pMicromaps: ptr VkMicromapEXT, queryType: VkQueryType, dataSize: csize_t, pData: pointer, stride: csize_t): VkResult {.stdcall.} - vkCmdCopyMicromapEXT*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMicromapInfoEXT): void {.stdcall.} - vkCmdCopyMicromapToMemoryEXT*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMicromapToMemoryInfoEXT): void {.stdcall.} - vkCmdCopyMemoryToMicromapEXT*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMemoryToMicromapInfoEXT): void {.stdcall.} - vkCmdWriteMicromapsPropertiesEXT*: proc(commandBuffer: VkCommandBuffer, micromapCount: uint32, pMicromaps: ptr VkMicromapEXT, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.} - vkGetDeviceMicromapCompatibilityEXT*: proc(device: VkDevice, pVersionInfo: ptr VkMicromapVersionInfoEXT, pCompatibility: ptr VkAccelerationStructureCompatibilityKHR): void {.stdcall.} - vkGetMicromapBuildSizesEXT*: proc(device: VkDevice, buildType: VkAccelerationStructureBuildTypeKHR, pBuildInfo: ptr VkMicromapBuildInfoEXT, pSizeInfo: ptr VkMicromapBuildSizesInfoEXT): void {.stdcall.} -proc loadVK_EXT_opacity_micromap*(instance: VkInstance) = - loadVK_KHR_acceleration_structure(instance) - loadVK_VERSION_1_3(instance) - vkCreateMicromapEXT = cast[proc(device: VkDevice, pCreateInfo: ptr VkMicromapCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pMicromap: ptr VkMicromapEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateMicromapEXT")) - vkDestroyMicromapEXT = cast[proc(device: VkDevice, micromap: VkMicromapEXT, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyMicromapEXT")) - vkCmdBuildMicromapsEXT = cast[proc(commandBuffer: VkCommandBuffer, infoCount: uint32, pInfos: ptr VkMicromapBuildInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBuildMicromapsEXT")) - vkBuildMicromapsEXT = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, infoCount: uint32, pInfos: ptr VkMicromapBuildInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBuildMicromapsEXT")) - vkCopyMicromapEXT = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMicromapInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyMicromapEXT")) - vkCopyMicromapToMemoryEXT = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMicromapToMemoryInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyMicromapToMemoryEXT")) - vkCopyMemoryToMicromapEXT = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pInfo: ptr VkCopyMemoryToMicromapInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCopyMemoryToMicromapEXT")) - vkWriteMicromapsPropertiesEXT = cast[proc(device: VkDevice, micromapCount: uint32, pMicromaps: ptr VkMicromapEXT, queryType: VkQueryType, dataSize: csize_t, pData: pointer, stride: csize_t): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkWriteMicromapsPropertiesEXT")) - vkCmdCopyMicromapEXT = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMicromapInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMicromapEXT")) - vkCmdCopyMicromapToMemoryEXT = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMicromapToMemoryInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMicromapToMemoryEXT")) - vkCmdCopyMemoryToMicromapEXT = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkCopyMemoryToMicromapInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyMemoryToMicromapEXT")) - vkCmdWriteMicromapsPropertiesEXT = cast[proc(commandBuffer: VkCommandBuffer, micromapCount: uint32, pMicromaps: ptr VkMicromapEXT, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteMicromapsPropertiesEXT")) - vkGetDeviceMicromapCompatibilityEXT = cast[proc(device: VkDevice, pVersionInfo: ptr VkMicromapVersionInfoEXT, pCompatibility: ptr VkAccelerationStructureCompatibilityKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceMicromapCompatibilityEXT")) - vkGetMicromapBuildSizesEXT = cast[proc(device: VkDevice, buildType: VkAccelerationStructureBuildTypeKHR, pBuildInfo: ptr VkMicromapBuildInfoEXT, pSizeInfo: ptr VkMicromapBuildSizesInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMicromapBuildSizesEXT")) - -proc loadVK_KHR_incremental_present*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - -# extension VK_KHR_shared_presentable_image -var - vkGetSwapchainStatusKHR*: proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.} -proc loadVK_KHR_shared_presentable_image*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - loadVK_VERSION_1_1(instance) - loadVK_KHR_get_surface_capabilities2(instance) - vkGetSwapchainStatusKHR = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSwapchainStatusKHR")) - -# extension VK_EXT_hdr_metadata -var - vkSetHdrMetadataEXT*: proc(device: VkDevice, swapchainCount: uint32, pSwapchains: ptr VkSwapchainKHR, pMetadata: ptr VkHdrMetadataEXT): void {.stdcall.} -proc loadVK_EXT_hdr_metadata*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - vkSetHdrMetadataEXT = cast[proc(device: VkDevice, swapchainCount: uint32, pSwapchains: ptr VkSwapchainKHR, pMetadata: ptr VkHdrMetadataEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetHdrMetadataEXT")) - -proc loadVK_KHR_present_id*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - loadVK_VERSION_1_1(instance) - -# extension VK_KHR_ray_tracing_maintenance1 -var - vkCmdTraceRaysIndirect2KHR*: proc(commandBuffer: VkCommandBuffer, indirectDeviceAddress: VkDeviceAddress): void {.stdcall.} -proc loadVK_KHR_ray_tracing_maintenance1*(instance: VkInstance) = - loadVK_KHR_acceleration_structure(instance) - vkCmdTraceRaysIndirect2KHR = cast[proc(commandBuffer: VkCommandBuffer, indirectDeviceAddress: VkDeviceAddress): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdTraceRaysIndirect2KHR")) - -# extension VK_KHR_ray_tracing_pipeline -var - vkCmdTraceRaysKHR*: proc(commandBuffer: VkCommandBuffer, pRaygenShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pMissShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pHitShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pCallableShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, width: uint32, height: uint32, depth: uint32): void {.stdcall.} - vkCreateRayTracingPipelinesKHR*: proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkRayTracingPipelineCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.} - vkGetRayTracingShaderGroupHandlesKHR*: proc(device: VkDevice, pipeline: VkPipeline, firstGroup: uint32, groupCount: uint32, dataSize: csize_t, pData: pointer): VkResult {.stdcall.} - vkGetRayTracingCaptureReplayShaderGroupHandlesKHR*: proc(device: VkDevice, pipeline: VkPipeline, firstGroup: uint32, groupCount: uint32, dataSize: csize_t, pData: pointer): VkResult {.stdcall.} - vkCmdTraceRaysIndirectKHR*: proc(commandBuffer: VkCommandBuffer, pRaygenShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pMissShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pHitShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pCallableShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, indirectDeviceAddress: VkDeviceAddress): void {.stdcall.} - vkGetRayTracingShaderGroupStackSizeKHR*: proc(device: VkDevice, pipeline: VkPipeline, group: uint32, groupShader: VkShaderGroupShaderKHR): VkDeviceSize {.stdcall.} - vkCmdSetRayTracingPipelineStackSizeKHR*: proc(commandBuffer: VkCommandBuffer, pipelineStackSize: uint32): void {.stdcall.} -proc loadVK_KHR_ray_tracing_pipeline*(instance: VkInstance) = - loadVK_VERSION_1_2(instance) - loadVK_KHR_acceleration_structure(instance) - vkCmdTraceRaysKHR = cast[proc(commandBuffer: VkCommandBuffer, pRaygenShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pMissShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pHitShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pCallableShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, width: uint32, height: uint32, depth: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdTraceRaysKHR")) - vkCreateRayTracingPipelinesKHR = cast[proc(device: VkDevice, deferredOperation: VkDeferredOperationKHR, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkRayTracingPipelineCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateRayTracingPipelinesKHR")) - vkGetRayTracingShaderGroupHandlesKHR = cast[proc(device: VkDevice, pipeline: VkPipeline, firstGroup: uint32, groupCount: uint32, dataSize: csize_t, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRayTracingShaderGroupHandlesKHR")) - vkGetRayTracingCaptureReplayShaderGroupHandlesKHR = cast[proc(device: VkDevice, pipeline: VkPipeline, firstGroup: uint32, groupCount: uint32, dataSize: csize_t, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR")) - vkCmdTraceRaysIndirectKHR = cast[proc(commandBuffer: VkCommandBuffer, pRaygenShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pMissShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pHitShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, pCallableShaderBindingTable: ptr VkStridedDeviceAddressRegionKHR, indirectDeviceAddress: VkDeviceAddress): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdTraceRaysIndirectKHR")) - vkGetRayTracingShaderGroupStackSizeKHR = cast[proc(device: VkDevice, pipeline: VkPipeline, group: uint32, groupShader: VkShaderGroupShaderKHR): VkDeviceSize {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRayTracingShaderGroupStackSizeKHR")) - vkCmdSetRayTracingPipelineStackSizeKHR = cast[proc(commandBuffer: VkCommandBuffer, pipelineStackSize: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdSetRayTracingPipelineStackSizeKHR")) - -# extension VK_HUAWEI_invocation_mask -var - vkCmdBindInvocationMaskHUAWEI*: proc(commandBuffer: VkCommandBuffer, imageView: VkImageView, imageLayout: VkImageLayout): void {.stdcall.} -proc loadVK_HUAWEI_invocation_mask*(instance: VkInstance) = - loadVK_KHR_ray_tracing_pipeline(instance) - loadVK_VERSION_1_3(instance) - vkCmdBindInvocationMaskHUAWEI = cast[proc(commandBuffer: VkCommandBuffer, imageView: VkImageView, imageLayout: VkImageLayout): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBindInvocationMaskHUAWEI")) - -# extension VK_EXT_display_surface_counter -var - vkGetPhysicalDeviceSurfaceCapabilities2EXT*: proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceCapabilities: ptr VkSurfaceCapabilities2EXT): VkResult {.stdcall.} -proc loadVK_EXT_display_surface_counter*(instance: VkInstance) = - loadVK_KHR_display(instance) - vkGetPhysicalDeviceSurfaceCapabilities2EXT = cast[proc(physicalDevice: VkPhysicalDevice, surface: VkSurfaceKHR, pSurfaceCapabilities: ptr VkSurfaceCapabilities2EXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2EXT")) - -# extension VK_KHR_get_display_properties2 -var - vkGetPhysicalDeviceDisplayProperties2KHR*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayProperties2KHR): VkResult {.stdcall.} - vkGetPhysicalDeviceDisplayPlaneProperties2KHR*: proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPlaneProperties2KHR): VkResult {.stdcall.} - vkGetDisplayModeProperties2KHR*: proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayModeProperties2KHR): VkResult {.stdcall.} - vkGetDisplayPlaneCapabilities2KHR*: proc(physicalDevice: VkPhysicalDevice, pDisplayPlaneInfo: ptr VkDisplayPlaneInfo2KHR, pCapabilities: ptr VkDisplayPlaneCapabilities2KHR): VkResult {.stdcall.} -proc loadVK_KHR_get_display_properties2*(instance: VkInstance) = - loadVK_KHR_display(instance) - vkGetPhysicalDeviceDisplayProperties2KHR = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayProperties2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayProperties2KHR")) - vkGetPhysicalDeviceDisplayPlaneProperties2KHR = cast[proc(physicalDevice: VkPhysicalDevice, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayPlaneProperties2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR")) - vkGetDisplayModeProperties2KHR = cast[proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR, pPropertyCount: ptr uint32, pProperties: ptr VkDisplayModeProperties2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDisplayModeProperties2KHR")) - vkGetDisplayPlaneCapabilities2KHR = cast[proc(physicalDevice: VkPhysicalDevice, pDisplayPlaneInfo: ptr VkDisplayPlaneInfo2KHR, pCapabilities: ptr VkDisplayPlaneCapabilities2KHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilities2KHR")) - -proc loadVK_KHR_ray_query*(instance: VkInstance) = - loadVK_VERSION_1_2(instance) - loadVK_KHR_acceleration_structure(instance) - -# extension VK_KHR_display_swapchain -var - vkCreateSharedSwapchainsKHR*: proc(device: VkDevice, swapchainCount: uint32, pCreateInfos: ptr VkSwapchainCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSwapchains: ptr VkSwapchainKHR): VkResult {.stdcall.} -proc loadVK_KHR_display_swapchain*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - loadVK_KHR_display(instance) - vkCreateSharedSwapchainsKHR = cast[proc(device: VkDevice, swapchainCount: uint32, pCreateInfos: ptr VkSwapchainCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSwapchains: ptr VkSwapchainKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateSharedSwapchainsKHR")) - -# extension VK_EXT_acquire_drm_display -var - vkAcquireDrmDisplayEXT*: proc(physicalDevice: VkPhysicalDevice, drmFd: int32, display: VkDisplayKHR): VkResult {.stdcall.} - vkGetDrmDisplayEXT*: proc(physicalDevice: VkPhysicalDevice, drmFd: int32, connectorId: uint32, display: ptr VkDisplayKHR): VkResult {.stdcall.} -proc loadVK_EXT_acquire_drm_display*(instance: VkInstance) = - loadVK_EXT_direct_mode_display(instance) - vkAcquireDrmDisplayEXT = cast[proc(physicalDevice: VkPhysicalDevice, drmFd: int32, display: VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireDrmDisplayEXT")) - vkGetDrmDisplayEXT = cast[proc(physicalDevice: VkPhysicalDevice, drmFd: int32, connectorId: uint32, display: ptr VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDrmDisplayEXT")) - -# extension VK_EXT_display_control -var - vkDisplayPowerControlEXT*: proc(device: VkDevice, display: VkDisplayKHR, pDisplayPowerInfo: ptr VkDisplayPowerInfoEXT): VkResult {.stdcall.} - vkRegisterDeviceEventEXT*: proc(device: VkDevice, pDeviceEventInfo: ptr VkDeviceEventInfoEXT, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.} - vkRegisterDisplayEventEXT*: proc(device: VkDevice, display: VkDisplayKHR, pDisplayEventInfo: ptr VkDisplayEventInfoEXT, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.} - vkGetSwapchainCounterEXT*: proc(device: VkDevice, swapchain: VkSwapchainKHR, counter: VkSurfaceCounterFlagBitsEXT, pCounterValue: ptr uint64): VkResult {.stdcall.} -proc loadVK_EXT_display_control*(instance: VkInstance) = - loadVK_EXT_display_surface_counter(instance) - loadVK_KHR_swapchain(instance) - vkDisplayPowerControlEXT = cast[proc(device: VkDevice, display: VkDisplayKHR, pDisplayPowerInfo: ptr VkDisplayPowerInfoEXT): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDisplayPowerControlEXT")) - vkRegisterDeviceEventEXT = cast[proc(device: VkDevice, pDeviceEventInfo: ptr VkDeviceEventInfoEXT, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkRegisterDeviceEventEXT")) - vkRegisterDisplayEventEXT = cast[proc(device: VkDevice, display: VkDisplayKHR, pDisplayEventInfo: ptr VkDisplayEventInfoEXT, pAllocator: ptr VkAllocationCallbacks, pFence: ptr VkFence): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkRegisterDisplayEventEXT")) - vkGetSwapchainCounterEXT = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, counter: VkSurfaceCounterFlagBitsEXT, pCounterValue: ptr uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSwapchainCounterEXT")) - -proc loadVK_NV_ray_tracing_motion_blur*(instance: VkInstance) = - loadVK_KHR_ray_tracing_pipeline(instance) - -proc loadVK_EXT_pipeline_library_group_handles*(instance: VkInstance) = - loadVK_KHR_ray_tracing_pipeline(instance) - loadVK_KHR_pipeline_library(instance) - -# extension VK_NV_ray_tracing -var - vkCreateAccelerationStructureNV*: proc(device: VkDevice, pCreateInfo: ptr VkAccelerationStructureCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pAccelerationStructure: ptr VkAccelerationStructureNV): VkResult {.stdcall.} - vkDestroyAccelerationStructureNV*: proc(device: VkDevice, accelerationStructure: VkAccelerationStructureNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetAccelerationStructureMemoryRequirementsNV*: proc(device: VkDevice, pInfo: ptr VkAccelerationStructureMemoryRequirementsInfoNV, pMemoryRequirements: ptr VkMemoryRequirements2KHR): void {.stdcall.} - vkBindAccelerationStructureMemoryNV*: proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindAccelerationStructureMemoryInfoNV): VkResult {.stdcall.} - vkCmdBuildAccelerationStructureNV*: proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkAccelerationStructureInfoNV, instanceData: VkBuffer, instanceOffset: VkDeviceSize, update: VkBool32, dst: VkAccelerationStructureNV, src: VkAccelerationStructureNV, scratch: VkBuffer, scratchOffset: VkDeviceSize): void {.stdcall.} - vkCmdCopyAccelerationStructureNV*: proc(commandBuffer: VkCommandBuffer, dst: VkAccelerationStructureNV, src: VkAccelerationStructureNV, mode: VkCopyAccelerationStructureModeKHR): void {.stdcall.} - vkCmdTraceRaysNV*: proc(commandBuffer: VkCommandBuffer, raygenShaderBindingTableBuffer: VkBuffer, raygenShaderBindingOffset: VkDeviceSize, missShaderBindingTableBuffer: VkBuffer, missShaderBindingOffset: VkDeviceSize, missShaderBindingStride: VkDeviceSize, hitShaderBindingTableBuffer: VkBuffer, hitShaderBindingOffset: VkDeviceSize, hitShaderBindingStride: VkDeviceSize, callableShaderBindingTableBuffer: VkBuffer, callableShaderBindingOffset: VkDeviceSize, callableShaderBindingStride: VkDeviceSize, width: uint32, height: uint32, depth: uint32): void {.stdcall.} - vkCreateRayTracingPipelinesNV*: proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkRayTracingPipelineCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.} - vkGetRayTracingShaderGroupHandlesNV*: proc(device: VkDevice, pipeline: VkPipeline, firstGroup: uint32, groupCount: uint32, dataSize: csize_t, pData: pointer): VkResult {.stdcall.} - vkGetAccelerationStructureHandleNV*: proc(device: VkDevice, accelerationStructure: VkAccelerationStructureNV, dataSize: csize_t, pData: pointer): VkResult {.stdcall.} - vkCmdWriteAccelerationStructuresPropertiesNV*: proc(commandBuffer: VkCommandBuffer, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureNV, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.} - vkCompileDeferredNV*: proc(device: VkDevice, pipeline: VkPipeline, shader: uint32): VkResult {.stdcall.} -proc loadVK_NV_ray_tracing*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_1(instance) - vkCreateAccelerationStructureNV = cast[proc(device: VkDevice, pCreateInfo: ptr VkAccelerationStructureCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pAccelerationStructure: ptr VkAccelerationStructureNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateAccelerationStructureNV")) - vkDestroyAccelerationStructureNV = cast[proc(device: VkDevice, accelerationStructure: VkAccelerationStructureNV, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyAccelerationStructureNV")) - vkGetAccelerationStructureMemoryRequirementsNV = cast[proc(device: VkDevice, pInfo: ptr VkAccelerationStructureMemoryRequirementsInfoNV, pMemoryRequirements: ptr VkMemoryRequirements2KHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureMemoryRequirementsNV")) - vkBindAccelerationStructureMemoryNV = cast[proc(device: VkDevice, bindInfoCount: uint32, pBindInfos: ptr VkBindAccelerationStructureMemoryInfoNV): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindAccelerationStructureMemoryNV")) - vkCmdBuildAccelerationStructureNV = cast[proc(commandBuffer: VkCommandBuffer, pInfo: ptr VkAccelerationStructureInfoNV, instanceData: VkBuffer, instanceOffset: VkDeviceSize, update: VkBool32, dst: VkAccelerationStructureNV, src: VkAccelerationStructureNV, scratch: VkBuffer, scratchOffset: VkDeviceSize): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBuildAccelerationStructureNV")) - vkCmdCopyAccelerationStructureNV = cast[proc(commandBuffer: VkCommandBuffer, dst: VkAccelerationStructureNV, src: VkAccelerationStructureNV, mode: VkCopyAccelerationStructureModeKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdCopyAccelerationStructureNV")) - vkCmdTraceRaysNV = cast[proc(commandBuffer: VkCommandBuffer, raygenShaderBindingTableBuffer: VkBuffer, raygenShaderBindingOffset: VkDeviceSize, missShaderBindingTableBuffer: VkBuffer, missShaderBindingOffset: VkDeviceSize, missShaderBindingStride: VkDeviceSize, hitShaderBindingTableBuffer: VkBuffer, hitShaderBindingOffset: VkDeviceSize, hitShaderBindingStride: VkDeviceSize, callableShaderBindingTableBuffer: VkBuffer, callableShaderBindingOffset: VkDeviceSize, callableShaderBindingStride: VkDeviceSize, width: uint32, height: uint32, depth: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdTraceRaysNV")) - vkCreateRayTracingPipelinesNV = cast[proc(device: VkDevice, pipelineCache: VkPipelineCache, createInfoCount: uint32, pCreateInfos: ptr VkRayTracingPipelineCreateInfoNV, pAllocator: ptr VkAllocationCallbacks, pPipelines: ptr VkPipeline): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateRayTracingPipelinesNV")) - vkGetRayTracingShaderGroupHandlesNV = vkGetRayTracingShaderGroupHandlesKHR - vkGetAccelerationStructureHandleNV = cast[proc(device: VkDevice, accelerationStructure: VkAccelerationStructureNV, dataSize: csize_t, pData: pointer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureHandleNV")) - vkCmdWriteAccelerationStructuresPropertiesNV = cast[proc(commandBuffer: VkCommandBuffer, accelerationStructureCount: uint32, pAccelerationStructures: ptr VkAccelerationStructureNV, queryType: VkQueryType, queryPool: VkQueryPool, firstQuery: uint32): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdWriteAccelerationStructuresPropertiesNV")) - vkCompileDeferredNV = cast[proc(device: VkDevice, pipeline: VkPipeline, shader: uint32): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCompileDeferredNV")) - -# extension VK_KHR_present_wait -var - vkWaitForPresentKHR*: proc(device: VkDevice, swapchain: VkSwapchainKHR, presentId: uint64, timeout: uint64): VkResult {.stdcall.} -proc loadVK_KHR_present_wait*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - loadVK_KHR_present_id(instance) - vkWaitForPresentKHR = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR, presentId: uint64, timeout: uint64): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkWaitForPresentKHR")) - -proc loadVK_NV_ray_tracing_invocation_reorder*(instance: VkInstance) = - loadVK_KHR_ray_tracing_pipeline(instance) - -var EXTENSION_LOADERS = { - "VK_NV_optical_flow": loadVK_NV_optical_flow, - "VK_EXT_vertex_attribute_divisor": loadVK_EXT_vertex_attribute_divisor, - "VK_EXT_pipeline_library_group_handles": loadVK_EXT_pipeline_library_group_handles, - "VK_NV_geometry_shader_passthrough": loadVK_NV_geometry_shader_passthrough, - "VK_EXT_line_rasterization": loadVK_EXT_line_rasterization, - "VK_EXT_rasterization_order_attachment_access": loadVK_EXT_rasterization_order_attachment_access, - "VK_EXT_shader_atomic_float2": loadVK_EXT_shader_atomic_float2, - "VK_IMG_format_pvrtc": loadVK_IMG_format_pvrtc, - "VK_AMD_texture_gather_bias_lod": loadVK_AMD_texture_gather_bias_lod, - "VK_KHR_shader_subgroup_uniform_control_flow": loadVK_KHR_shader_subgroup_uniform_control_flow, - "VK_AMD_shader_fragment_mask": loadVK_AMD_shader_fragment_mask, - "VK_EXT_external_memory_dma_buf": loadVK_EXT_external_memory_dma_buf, - "VK_IMG_filter_cubic": loadVK_IMG_filter_cubic, - "VK_EXT_pageable_device_local_memory": loadVK_EXT_pageable_device_local_memory, - "VK_EXT_primitive_topology_list_restart": loadVK_EXT_primitive_topology_list_restart, - "VK_KHR_global_priority": loadVK_KHR_global_priority, - "VK_AMD_shader_ballot": loadVK_AMD_shader_ballot, - "VK_AMD_buffer_marker": loadVK_AMD_buffer_marker, - "VK_NV_corner_sampled_image": loadVK_NV_corner_sampled_image, - "VK_NV_ray_tracing_invocation_reorder": loadVK_NV_ray_tracing_invocation_reorder, - "VK_QCOM_image_processing": loadVK_QCOM_image_processing, - "VK_AMD_shader_info": loadVK_AMD_shader_info, - "VK_KHR_pipeline_library": loadVK_KHR_pipeline_library, - "VK_EXT_blend_operation_advanced": loadVK_EXT_blend_operation_advanced, - "VK_AMD_gpu_shader_int16": loadVK_AMD_gpu_shader_int16, - "VK_EXT_pipeline_robustness": loadVK_EXT_pipeline_robustness, - "VK_NV_scissor_exclusive": loadVK_NV_scissor_exclusive, - "VK_EXT_sample_locations": loadVK_EXT_sample_locations, - "VK_NV_framebuffer_mixed_samples": loadVK_NV_framebuffer_mixed_samples, - "VK_NV_sample_mask_override_coverage": loadVK_NV_sample_mask_override_coverage, - "VK_KHR_present_id": loadVK_KHR_present_id, - "VK_EXT_descriptor_buffer": loadVK_EXT_descriptor_buffer, - "VK_EXT_filter_cubic": loadVK_EXT_filter_cubic, - "VK_KHR_pipeline_executable_properties": loadVK_KHR_pipeline_executable_properties, - "VK_EXT_extended_dynamic_state3": loadVK_EXT_extended_dynamic_state3, - "VK_KHR_performance_query": loadVK_KHR_performance_query, - "VK_GOOGLE_user_type": loadVK_GOOGLE_user_type, - "VK_KHR_ray_tracing_maintenance1": loadVK_KHR_ray_tracing_maintenance1, - "VK_EXT_debug_report": loadVK_EXT_debug_report, - "VK_EXT_multisampled_render_to_single_sampled": loadVK_EXT_multisampled_render_to_single_sampled, - "VK_EXT_device_address_binding_report": loadVK_EXT_device_address_binding_report, - "VK_NV_clip_space_w_scaling": loadVK_NV_clip_space_w_scaling, - "VK_NV_fill_rectangle": loadVK_NV_fill_rectangle, - "VK_EXT_shader_image_atomic_int64": loadVK_EXT_shader_image_atomic_int64, - "VK_KHR_swapchain": loadVK_KHR_swapchain, - "VK_NV_ray_tracing": loadVK_NV_ray_tracing, - "VK_EXT_swapchain_maintenance1": loadVK_EXT_swapchain_maintenance1, - "VK_KHR_ray_tracing_pipeline": loadVK_KHR_ray_tracing_pipeline, - "VK_EXT_ycbcr_image_arrays": loadVK_EXT_ycbcr_image_arrays, - "VK_AMD_negative_viewport_height": loadVK_AMD_negative_viewport_height, - "VK_EXT_provoking_vertex": loadVK_EXT_provoking_vertex, - "VK_EXT_calibrated_timestamps": loadVK_EXT_calibrated_timestamps, - "VK_EXT_attachment_feedback_loop_layout": loadVK_EXT_attachment_feedback_loop_layout, - "VK_AMD_mixed_attachment_samples": loadVK_AMD_mixed_attachment_samples, - "VK_HUAWEI_invocation_mask": loadVK_HUAWEI_invocation_mask, - "VK_EXT_external_memory_host": loadVK_EXT_external_memory_host, - "VK_NV_device_diagnostics_config": loadVK_NV_device_diagnostics_config, - "VK_EXT_fragment_density_map2": loadVK_EXT_fragment_density_map2, - "VK_NV_shader_subgroup_partitioned": loadVK_NV_shader_subgroup_partitioned, - "VK_EXT_image_sliced_view_of_3d": loadVK_EXT_image_sliced_view_of_3d, - "VK_NV_fragment_shading_rate_enums": loadVK_NV_fragment_shading_rate_enums, - "VK_EXT_display_surface_counter": loadVK_EXT_display_surface_counter, - "VK_ARM_shader_core_properties": loadVK_ARM_shader_core_properties, - "VK_EXT_shader_module_identifier": loadVK_EXT_shader_module_identifier, - "VK_EXT_border_color_swizzle": loadVK_EXT_border_color_swizzle, - "VK_AMD_shader_image_load_store_lod": loadVK_AMD_shader_image_load_store_lod, - "VK_AMD_display_native_hdr": loadVK_AMD_display_native_hdr, - "VK_NV_memory_decompression": loadVK_NV_memory_decompression, - "VK_EXT_direct_mode_display": loadVK_EXT_direct_mode_display, - "VK_EXT_fragment_shader_interlock": loadVK_EXT_fragment_shader_interlock, - "VK_NV_coverage_reduction_mode": loadVK_NV_coverage_reduction_mode, - "VK_KHR_get_display_properties2": loadVK_KHR_get_display_properties2, - "VK_INTEL_shader_integer_functions2": loadVK_INTEL_shader_integer_functions2, - "VK_NV_glsl_shader": loadVK_NV_glsl_shader, - "VK_KHR_shader_clock": loadVK_KHR_shader_clock, - "VK_EXT_image_2d_view_of_3d": loadVK_EXT_image_2d_view_of_3d, - "VK_QCOM_tile_properties": loadVK_QCOM_tile_properties, - "VK_KHR_push_descriptor": loadVK_KHR_push_descriptor, - "VK_NV_viewport_swizzle": loadVK_NV_viewport_swizzle, - "VK_KHR_ray_query": loadVK_KHR_ray_query, - "VK_KHR_present_wait": loadVK_KHR_present_wait, - "VK_NV_shading_rate_image": loadVK_NV_shading_rate_image, - "VK_EXT_fragment_density_map": loadVK_EXT_fragment_density_map, - "VK_NV_device_diagnostic_checkpoints": loadVK_NV_device_diagnostic_checkpoints, - "VK_EXT_pci_bus_info": loadVK_EXT_pci_bus_info, - "VK_NV_external_memory": loadVK_NV_external_memory, - "VK_EXT_queue_family_foreign": loadVK_EXT_queue_family_foreign, - "VK_KHR_swapchain_mutable_format": loadVK_KHR_swapchain_mutable_format, - "VK_EXT_depth_clip_control": loadVK_EXT_depth_clip_control, - "VK_EXT_debug_utils": loadVK_EXT_debug_utils, - "VK_KHR_portability_enumeration": loadVK_KHR_portability_enumeration, - "VK_EXT_memory_priority": loadVK_EXT_memory_priority, - "VK_EXT_validation_flags": loadVK_EXT_validation_flags, - "VK_AMD_shader_core_properties": loadVK_AMD_shader_core_properties, - "VK_EXT_conservative_rasterization": loadVK_EXT_conservative_rasterization, - "VK_KHR_external_fence_fd": loadVK_KHR_external_fence_fd, - "VK_NV_device_generated_commands": loadVK_NV_device_generated_commands, - "VK_NV_present_barrier": loadVK_NV_present_barrier, - "VK_AMD_gcn_shader": loadVK_AMD_gcn_shader, - "VK_NV_viewport_array2": loadVK_NV_viewport_array2, - "VK_INTEL_performance_query": loadVK_INTEL_performance_query, - "VK_NVX_multiview_per_view_attributes": loadVK_NVX_multiview_per_view_attributes, - "VK_EXT_primitives_generated_query": loadVK_EXT_primitives_generated_query, - "VK_AMD_pipeline_compiler_control": loadVK_AMD_pipeline_compiler_control, - "VK_EXT_post_depth_coverage": loadVK_EXT_post_depth_coverage, - "VK_EXT_rgba10x6_formats": loadVK_EXT_rgba10x6_formats, - "VK_KHR_external_memory_fd": loadVK_KHR_external_memory_fd, - "VK_NV_dedicated_allocation_image_aliasing": loadVK_NV_dedicated_allocation_image_aliasing, - "VK_NV_cooperative_matrix": loadVK_NV_cooperative_matrix, - "VK_EXT_depth_clamp_zero_one": loadVK_EXT_depth_clamp_zero_one, - "VK_EXT_conditional_rendering": loadVK_EXT_conditional_rendering, - "VK_QCOM_multiview_per_view_viewports": loadVK_QCOM_multiview_per_view_viewports, - "VK_NV_linear_color_attachment": loadVK_NV_linear_color_attachment, - "VK_EXT_shader_subgroup_ballot": loadVK_EXT_shader_subgroup_ballot, - "VK_EXT_multi_draw": loadVK_EXT_multi_draw, - "VK_NV_fragment_coverage_to_color": loadVK_NV_fragment_coverage_to_color, - "VK_EXT_load_store_op_none": loadVK_EXT_load_store_op_none, - "VK_QCOM_rotated_copy_commands": loadVK_QCOM_rotated_copy_commands, - "VK_EXT_surface_maintenance1": loadVK_EXT_surface_maintenance1, - "VK_EXT_swapchain_colorspace": loadVK_EXT_swapchain_colorspace, - "VK_EXT_image_drm_format_modifier": loadVK_EXT_image_drm_format_modifier, - "VK_EXT_validation_features": loadVK_EXT_validation_features, - "VK_KHR_workgroup_memory_explicit_layout": loadVK_KHR_workgroup_memory_explicit_layout, - "VK_EXT_index_type_uint8": loadVK_EXT_index_type_uint8, - "VK_EXT_mesh_shader": loadVK_EXT_mesh_shader, - "VK_AMD_shader_early_and_late_fragment_tests": loadVK_AMD_shader_early_and_late_fragment_tests, - "VK_KHR_display_swapchain": loadVK_KHR_display_swapchain, - "VK_EXT_transform_feedback": loadVK_EXT_transform_feedback, - "VK_GOOGLE_decorate_string": loadVK_GOOGLE_decorate_string, - "VK_EXT_shader_atomic_float": loadVK_EXT_shader_atomic_float, - "VK_EXT_acquire_drm_display": loadVK_EXT_acquire_drm_display, - "VK_EXT_pipeline_properties": loadVK_EXT_pipeline_properties, - "VK_EXT_graphics_pipeline_library": loadVK_EXT_graphics_pipeline_library, - "VK_KHR_acceleration_structure": loadVK_KHR_acceleration_structure, - "VK_AMD_shader_core_properties2": loadVK_AMD_shader_core_properties2, - "VK_KHR_surface": loadVK_KHR_surface, - "VK_AMD_gpu_shader_half_float": loadVK_AMD_gpu_shader_half_float, - "VK_KHR_deferred_host_operations": loadVK_KHR_deferred_host_operations, - "VK_NV_dedicated_allocation": loadVK_NV_dedicated_allocation, - "VK_GOOGLE_hlsl_functionality1": loadVK_GOOGLE_hlsl_functionality1, - "VK_EXT_robustness2": loadVK_EXT_robustness2, - "VK_NVX_image_view_handle": loadVK_NVX_image_view_handle, - "VK_EXT_non_seamless_cube_map": loadVK_EXT_non_seamless_cube_map, - "VK_EXT_opacity_micromap": loadVK_EXT_opacity_micromap, - "VK_EXT_image_view_min_lod": loadVK_EXT_image_view_min_lod, - "VK_AMD_shader_trinary_minmax": loadVK_AMD_shader_trinary_minmax, - "VK_QCOM_render_pass_store_ops": loadVK_QCOM_render_pass_store_ops, - "VK_EXT_device_fault": loadVK_EXT_device_fault, - "VK_EXT_custom_border_color": loadVK_EXT_custom_border_color, - "VK_EXT_mutable_descriptor_type": loadVK_EXT_mutable_descriptor_type, - "VK_AMD_rasterization_order": loadVK_AMD_rasterization_order, - "VK_EXT_vertex_input_dynamic_state": loadVK_EXT_vertex_input_dynamic_state, - "VK_KHR_incremental_present": loadVK_KHR_incremental_present, - "VK_KHR_fragment_shading_rate": loadVK_KHR_fragment_shading_rate, - "VK_EXT_color_write_enable": loadVK_EXT_color_write_enable, - "VK_SEC_amigo_profiling": loadVK_SEC_amigo_profiling, - "VK_GOOGLE_display_timing": loadVK_GOOGLE_display_timing, - "VK_NVX_binary_import": loadVK_NVX_binary_import, - "VK_EXT_depth_clip_enable": loadVK_EXT_depth_clip_enable, - "VK_EXT_subpass_merge_feedback": loadVK_EXT_subpass_merge_feedback, - "VK_NV_representative_fragment_test": loadVK_NV_representative_fragment_test, - "VK_EXT_validation_cache": loadVK_EXT_validation_cache, - "VK_EXT_display_control": loadVK_EXT_display_control, - "VK_KHR_external_semaphore_fd": loadVK_KHR_external_semaphore_fd, - "VK_KHR_fragment_shader_barycentric": loadVK_KHR_fragment_shader_barycentric, - "VK_NV_inherited_viewport_scissor": loadVK_NV_inherited_viewport_scissor, - "VK_EXT_legacy_dithering": loadVK_EXT_legacy_dithering, - "VK_NV_ray_tracing_motion_blur": loadVK_NV_ray_tracing_motion_blur, - "VK_EXT_physical_device_drm": loadVK_EXT_physical_device_drm, - "VK_EXT_pipeline_protected_access": loadVK_EXT_pipeline_protected_access, - "VK_QCOM_render_pass_transform": loadVK_QCOM_render_pass_transform, - "VK_GOOGLE_surfaceless_query": loadVK_GOOGLE_surfaceless_query, - "VK_EXT_memory_budget": loadVK_EXT_memory_budget, - "VK_EXT_discard_rectangles": loadVK_EXT_discard_rectangles, - "VK_EXT_shader_stencil_export": loadVK_EXT_shader_stencil_export, - "VK_KHR_shared_presentable_image": loadVK_KHR_shared_presentable_image, - "VK_NV_external_memory_rdma": loadVK_NV_external_memory_rdma, - "VK_EXT_image_compression_control_swapchain": loadVK_EXT_image_compression_control_swapchain, - "VK_EXT_hdr_metadata": loadVK_EXT_hdr_metadata, - "VK_AMD_device_coherent_memory": loadVK_AMD_device_coherent_memory, - "VK_EXT_device_memory_report": loadVK_EXT_device_memory_report, - "VK_ARM_shader_core_builtins": loadVK_ARM_shader_core_builtins, - "VK_QCOM_multiview_per_view_render_areas": loadVK_QCOM_multiview_per_view_render_areas, - "VK_LUNARG_direct_driver_loading": loadVK_LUNARG_direct_driver_loading, - "VK_AMD_memory_overallocation_behavior": loadVK_AMD_memory_overallocation_behavior, - "VK_NV_mesh_shader": loadVK_NV_mesh_shader, - "VK_AMD_shader_explicit_vertex_parameter": loadVK_AMD_shader_explicit_vertex_parameter, - "VK_EXT_headless_surface": loadVK_EXT_headless_surface, - "VK_NV_shader_sm_builtins": loadVK_NV_shader_sm_builtins, - "VK_EXT_shader_subgroup_vote": loadVK_EXT_shader_subgroup_vote, - "VK_NV_copy_memory_indirect": loadVK_NV_copy_memory_indirect, - "VK_EXT_image_compression_control": loadVK_EXT_image_compression_control, - "VK_EXT_astc_decode_mode": loadVK_EXT_astc_decode_mode, - "VK_EXT_buffer_device_address": loadVK_EXT_buffer_device_address, - "VK_KHR_get_surface_capabilities2": loadVK_KHR_get_surface_capabilities2, - "VK_KHR_display": loadVK_KHR_display, - "VK_QCOM_render_pass_shader_resolve": loadVK_QCOM_render_pass_shader_resolve, - "VK_EXT_depth_range_unrestricted": loadVK_EXT_depth_range_unrestricted, - "VK_HUAWEI_subpass_shading": loadVK_HUAWEI_subpass_shading, - "VK_VALVE_descriptor_set_host_mapping": loadVK_VALVE_descriptor_set_host_mapping, - "VK_HUAWEI_cluster_culling_shader": loadVK_HUAWEI_cluster_culling_shader, - "VK_KHR_surface_protected_capabilities": loadVK_KHR_surface_protected_capabilities, - "VK_NV_shader_image_footprint": loadVK_NV_shader_image_footprint, - "VK_NV_external_memory_capabilities": loadVK_NV_external_memory_capabilities, - "VK_NV_compute_shader_derivatives": loadVK_NV_compute_shader_derivatives, - "VK_QCOM_fragment_density_map_offset": loadVK_QCOM_fragment_density_map_offset, -}.toTable -when defined(VK_USE_PLATFORM_XLIB_KHR): - include ../vulkan/platform/xlib - EXTENSION_LOADERS["VK_KHR_xlib_surface"] = loadVK_KHR_xlib_surface -when defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT): - include ../vulkan/platform/xlib_xrandr - EXTENSION_LOADERS["VK_EXT_acquire_xlib_display"] = loadVK_EXT_acquire_xlib_display -when defined(VK_USE_PLATFORM_XCB_KHR): - include ../vulkan/platform/xcb - EXTENSION_LOADERS["VK_KHR_xcb_surface"] = loadVK_KHR_xcb_surface -when defined(VK_USE_PLATFORM_WAYLAND_KHR): - include ../vulkan/platform/wayland - EXTENSION_LOADERS["VK_KHR_wayland_surface"] = loadVK_KHR_wayland_surface -when defined(VK_USE_PLATFORM_DIRECTFB_EXT): - include ../vulkan/platform/directfb - EXTENSION_LOADERS["VK_EXT_directfb_surface"] = loadVK_EXT_directfb_surface -when defined(VK_USE_PLATFORM_ANDROID_KHR): - include ../vulkan/platform/android - EXTENSION_LOADERS["VK_KHR_android_surface"] = loadVK_KHR_android_surface - EXTENSION_LOADERS["VK_ANDROID_external_memory_android_hardware_buffer"] = loadVK_ANDROID_external_memory_android_hardware_buffer -when defined(VK_USE_PLATFORM_WIN32_KHR): - include ../vulkan/platform/win32 - EXTENSION_LOADERS["VK_KHR_external_semaphore_win32"] = loadVK_KHR_external_semaphore_win32 - EXTENSION_LOADERS["VK_EXT_full_screen_exclusive"] = loadVK_EXT_full_screen_exclusive - EXTENSION_LOADERS["VK_NV_external_memory_win32"] = loadVK_NV_external_memory_win32 - EXTENSION_LOADERS["VK_KHR_external_memory_win32"] = loadVK_KHR_external_memory_win32 - EXTENSION_LOADERS["VK_NV_acquire_winrt_display"] = loadVK_NV_acquire_winrt_display - EXTENSION_LOADERS["VK_KHR_win32_surface"] = loadVK_KHR_win32_surface - EXTENSION_LOADERS["VK_KHR_external_fence_win32"] = loadVK_KHR_external_fence_win32 - EXTENSION_LOADERS["VK_KHR_win32_keyed_mutex"] = loadVK_KHR_win32_keyed_mutex -when defined(VK_USE_PLATFORM_VI_NN): - include ../vulkan/platform/vi - EXTENSION_LOADERS["VK_NN_vi_surface"] = loadVK_NN_vi_surface -when defined(VK_USE_PLATFORM_IOS_MVK): - include ../vulkan/platform/ios - EXTENSION_LOADERS["VK_MVK_ios_surface"] = loadVK_MVK_ios_surface -when defined(VK_USE_PLATFORM_MACOS_MVK): - include ../vulkan/platform/macos - EXTENSION_LOADERS["VK_MVK_macos_surface"] = loadVK_MVK_macos_surface -when defined(VK_USE_PLATFORM_METAL_EXT): - include ../vulkan/platform/metal - EXTENSION_LOADERS["VK_EXT_metal_objects"] = loadVK_EXT_metal_objects - EXTENSION_LOADERS["VK_EXT_metal_surface"] = loadVK_EXT_metal_surface -when defined(VK_USE_PLATFORM_FUCHSIA): - include ../vulkan/platform/fuchsia - EXTENSION_LOADERS["VK_FUCHSIA_external_semaphore"] = loadVK_FUCHSIA_external_semaphore - EXTENSION_LOADERS["VK_FUCHSIA_imagepipe_surface"] = loadVK_FUCHSIA_imagepipe_surface - EXTENSION_LOADERS["VK_FUCHSIA_external_memory"] = loadVK_FUCHSIA_external_memory - EXTENSION_LOADERS["VK_FUCHSIA_buffer_collection"] = loadVK_FUCHSIA_buffer_collection -when defined(VK_USE_PLATFORM_GGP): - include ../vulkan/platform/ggp - EXTENSION_LOADERS["VK_GGP_frame_token"] = loadVK_GGP_frame_token - EXTENSION_LOADERS["VK_GGP_stream_descriptor_surface"] = loadVK_GGP_stream_descriptor_surface -when defined(VK_USE_PLATFORM_SCI): - include ../vulkan/platform/sci -when defined(VK_ENABLE_BETA_EXTENSIONS): - include ../vulkan/platform/provisional - EXTENSION_LOADERS["VK_KHR_video_encode_queue"] = loadVK_KHR_video_encode_queue - EXTENSION_LOADERS["VK_KHR_video_queue"] = loadVK_KHR_video_queue - EXTENSION_LOADERS["VK_EXT_video_encode_h264"] = loadVK_EXT_video_encode_h264 - EXTENSION_LOADERS["VK_EXT_video_encode_h265"] = loadVK_EXT_video_encode_h265 - EXTENSION_LOADERS["VK_KHR_video_decode_queue"] = loadVK_KHR_video_decode_queue - EXTENSION_LOADERS["VK_KHR_video_decode_h264"] = loadVK_KHR_video_decode_h264 - EXTENSION_LOADERS["VK_KHR_portability_subset"] = loadVK_KHR_portability_subset - EXTENSION_LOADERS["VK_KHR_video_decode_h265"] = loadVK_KHR_video_decode_h265 -when defined(VK_USE_PLATFORM_SCREEN_QNX): - include ../vulkan/platform/screen - EXTENSION_LOADERS["VK_QNX_screen_surface"] = loadVK_QNX_screen_surface - -proc loadExtension*(instance: VkInstance, extension: string) = - if extension in EXTENSION_LOADERS: - EXTENSION_LOADERS[extension](instance) - -# load global functions immediately -block globalFunctions: - let instance = VkInstance(0) - vkEnumerateInstanceVersion = cast[proc(pApiVersion: ptr uint32): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumerateInstanceVersion")) - vkEnumerateInstanceExtensionProperties = cast[proc(pLayerName: cstring, pPropertyCount: ptr uint32, pProperties: ptr VkExtensionProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumerateInstanceExtensionProperties")) - vkEnumerateInstanceLayerProperties = cast[proc(pPropertyCount: ptr uint32, pProperties: ptr VkLayerProperties): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkEnumerateInstanceLayerProperties")) - vkCreateInstance = cast[proc(pCreateInfo: ptr VkInstanceCreateInfo, pAllocator: ptr VkAllocationCallbacks, pInstance: ptr VkInstance): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateInstance")) - -converter NimBool2VkBool*(a: bool): VkBool32 = VkBool32(a) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/engine.nim --- a/src/semicongine/engine.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -import std/options -import std/logging -import std/os - -import ./platform/window - -import ./core -import ./vulkan/instance -import ./vulkan/device -import ./vulkan/physicaldevice -import ./vulkan/shader - -import ./scene -import ./material -import ./renderer -import ./events -import ./audio -import ./text - -type - EngineState* = enum - Starting - Running - Shutdown - Input = object - keyIsDown: set[Key] - keyWasPressed: set[Key] - keyWasReleased: set[Key] - mouseIsDown: set[MouseButton] - mouseWasPressed: set[MouseButton] - mouseWasReleased: set[MouseButton] - mousePosition: Vec2f - mouseMove: Vec2f - eventsProcessed: uint64 - windowWasResized: bool - mouseWheel: float32 - Engine* = object - state*: EngineState - device: Device - debugger: Debugger - instance: Instance - window: NativeWindow - renderer: Option[Renderer] - input: Input - exitHandler: proc(engine: var Engine) - resizeHandler: proc(engine: var Engine) - eventHandler: proc(engine: var Engine, event: Event) - - -proc destroy*(engine: var Engine) = - checkVkResult engine.device.vk.vkDeviceWaitIdle() - if engine.renderer.isSome: - engine.renderer.get.destroy() - engine.device.destroy() - if engine.debugger.messenger.valid: - engine.debugger.destroy() - engine.window.destroy() - engine.instance.destroy() - - -proc initEngine*( - applicationName: string, - debug=DEBUG, - exitHandler: proc(engine: var Engine) = nil, - resizeHandler: proc(engine: var Engine) = nil, - eventHandler: proc(engine: var Engine, event: Event) = nil -): Engine = - echo "Set log level to ", ENGINE_LOGLEVEL - setLogFilter(ENGINE_LOGLEVEL) - - result.state = Starting - result.exitHandler = exitHandler - result.resizeHandler = resizeHandler - result.eventHandler = eventHandler - result.window = createWindow(applicationName) - - var - instanceExtensions: seq[string] - enabledLayers: seq[string] - - if debug: - instanceExtensions.add "VK_EXT_debug_utils" - enabledLayers.add "VK_LAYER_KHRONOS_validation" - # putEnv("VK_LAYER_ENABLES", "VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT") - putEnv("VK_LAYER_ENABLES", "") - - if defined(linux) and DEBUG: - enabledLayers.add "VK_LAYER_MESA_overlay" - result.instance = result.window.createInstance( - vulkanVersion=VK_MAKE_API_VERSION(0, 1, 3, 0), - instanceExtensions=instanceExtensions, - layers=enabledLayers, - ) - if debug: - result.debugger = result.instance.createDebugMessenger() - # create devices - let selectedPhysicalDevice = result.instance.getPhysicalDevices().filterBestGraphics() - result.device = result.instance.createDevice( - selectedPhysicalDevice, - enabledLayers = @[], - enabledExtensions = @[], - selectedPhysicalDevice.filterForGraphicsPresentationQueues() - ) - startMixerThread() - -proc initRenderer*(engine: var Engine, shaders: openArray[(MaterialType, ShaderConfiguration)], clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32]), backFaceCulling=true) = - - assert not engine.renderer.isSome - var allShaders = @shaders - allShaders.add (TEXT_MATERIAL_TYPE, TEXT_SHADER) - engine.renderer = some(engine.device.initRenderer(shaders=allShaders, clearColor=clearColor, backFaceCulling=backFaceCulling)) - -proc initRenderer*(engine: var Engine, clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32])) = - engine.initRenderer(@[], clearColor) - -proc loadScene*(engine: var Engine, scene: var Scene) = - assert engine.renderer.isSome - assert not scene.loaded - engine.renderer.get.setupDrawableBuffers(scene) - engine.renderer.get.updateMeshData(scene, forceAll=true) - engine.renderer.get.updateUniformData(scene, forceAll=true) - -proc unloadScene*(engine: var Engine, scene: Scene) = - engine.renderer.get.destroy(scene) - -proc renderScene*(engine: var Engine, scene: var Scene) = - assert engine.state == Running - assert engine.renderer.isSome - engine.renderer.get.updateMeshData(scene) - engine.renderer.get.updateUniformData(scene) - engine.renderer.get.render(scene) - -proc updateInputs*(engine: var Engine): EngineState = - assert engine.state in [Starting, Running] - - # reset input states - engine.input.keyWasPressed = {} - engine.input.keyWasReleased = {} - engine.input.mouseWasPressed = {} - engine.input.mouseWasReleased = {} - engine.input.mouseWheel = 0 - engine.input.mouseMove = newVec2f() - engine.input.windowWasResized = false - - if engine.state == Starting: - engine.input.windowWasResized = true - var mpos = engine.window.getMousePosition() - if mpos.isSome: - engine.input.mousePosition = mpos.get - - var killed = false - for event in engine.window.pendingEvents(): - inc engine.input.eventsProcessed - if engine.eventHandler != nil: - engine.eventHandler(engine, event) - case event.eventType: - of Quit: - killed = true - of ResizedWindow: - engine.input.windowWasResized = true - of KeyPressed: - engine.input.keyWasPressed.incl event.key - engine.input.keyIsDown.incl event.key - of KeyReleased: - engine.input.keyWasReleased.incl event.key - engine.input.keyIsDown.excl event.key - of MousePressed: - engine.input.mouseWasPressed.incl event.button - engine.input.mouseIsDown.incl event.button - of MouseReleased: - engine.input.mouseWasReleased.incl event.button - engine.input.mouseIsDown.excl event.button - of MouseMoved: - let newPos = newVec2(float32(event.x), float32(event.y)) - engine.input.mouseMove = newPos - engine.input.mousePosition - engine.input.mousePosition = newPos - of MouseWheel: - engine.input.mouseWheel = event.amount - if engine.state == Starting: - engine.state = Running - if killed: - engine.state = Shutdown - if engine.exitHandler != nil: - engine.exitHandler(engine) - if engine.input.windowWasResized and engine.resizeHandler != nil: - engine.resizeHandler(engine) - return engine.state - -# wrappers for internal things -func keyIsDown*(engine: Engine, key: Key): auto = key in engine.input.keyIsDown -func keyWasPressed*(engine: Engine, key: Key): auto = key in engine.input.keyWasPressed -func keyWasPressed*(engine: Engine): auto = engine.input.keyWasPressed.len > 0 -func keyWasReleased*(engine: Engine, key: Key): auto = key in engine.input.keyWasReleased -func mouseIsDown*(engine: Engine, button: MouseButton): auto = button in engine.input.mouseIsDown -func mouseWasPressed*(engine: Engine, button: MouseButton): auto = button in engine.input.mouseWasPressed -func mouseWasReleased*(engine: Engine, button: MouseButton): auto = button in engine.input.mouseWasReleased -func mousePosition*(engine: Engine): auto = engine.input.mousePosition -func mousePositionNormalized*(engine: Engine): Vec2f = - result.x = (engine.input.mousePosition.x / float32(engine.window.size[0])) * 2.0 - 1.0 - result.y = (engine.input.mousePosition.y / float32(engine.window.size[1])) * 2.0 - 1.0 -func mouseMove*(engine: Engine): auto = engine.input.mouseMove -func mouseWheel*(engine: Engine): auto = engine.input.mouseWheel -func eventsProcessed*(engine: Engine): auto = engine.input.eventsProcessed -func framesRendered*(engine: Engine): uint64 = (if engine.renderer.isSome: engine.renderer.get.framesRendered else: 0) -func gpuDevice*(engine: Engine): Device = engine.device -func getWindow*(engine: Engine): auto = engine.window -func windowWasResized*(engine: Engine): auto = engine.input.windowWasResized -func showSystemCursor*(engine: Engine) = engine.window.showSystemCursor() -func hideSystemCursor*(engine: Engine) = engine.window.hideSystemCursor() -proc fullscreen*(engine: var Engine, enable: bool) = engine.window.fullscreen(enable) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/events.nim --- a/src/semicongine/events.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -type - EventType* = enum - Quit - ResizedWindow - KeyPressed, KeyReleased - MousePressed, MouseReleased, MouseMoved, - MouseWheel - Key* {.size: sizeof(cint), pure.} = enum - UNKNOWN - Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12 - NumberRowExtra1, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `0`, - NumberRowExtra2, NumberRowExtra3 # tilde, minus, plus - A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z - Tab, CapsLock, ShiftL, ShiftR, CtrlL, CtrlR, SuperL, SuperR, AltL, AltR, - Space, Enter, Backspace - LetterRow1Extra1, LetterRow1Extra2 # open bracket, close brackt, backslash - LetterRow2Extra1, LetterRow2Extra2, LetterRow2Extra3 # semicolon, quote - LetterRow3Extra1, LetterRow3Extra2, LetterRow3Extra3 # comma, period, slash - Up, Down, Left, Right - PageUp, PageDown, Home, End, Insert, Delete - PrintScreen, ScrollLock, Pause - MouseButton* {.size: sizeof(cint), pure.} = enum - UNKNOWN, Mouse1, Mouse2, Mouse3 - Event* = object - case eventType*: EventType - of KeyPressed, KeyReleased: - key*: Key - of MousePressed, MouseReleased: - button*: MouseButton - of MouseMoved: - x*, y*: int - of MouseWheel: - amount*: float32 - else: - discard diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/material.nim --- a/src/semicongine/material.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -import std/tables -import std/strformat -import std/strutils -import std/hashes - - -import ./core - -type - MaterialType* = object - name*: string - vertexAttributes*: Table[string, DataType] - instanceAttributes*: Table[string, DataType] - attributes*: Table[string, DataType] - MaterialData* = object - theType*: MaterialType - name*: string - attributes*: Table[string, DataList] - -proc hash*(materialType: MaterialType): Hash = - return hash(materialType.name) - -proc hash*(materialData: MaterialData): Hash = - return hash(materialData.name) - -proc `==`*(a, b: MaterialType): bool = - return a.name == b.name - -proc `==`*(a, b: MaterialData): bool = - return a.name == b.name - -let EMPTY_MATERIAL* = MaterialType( - name: "empty material", - vertexAttributes: {"position": Vec3F32}.toTable, -) -let COLORED_MATERIAL* = MaterialType( - name: "single color material", - vertexAttributes: {"position": Vec3F32}.toTable, - attributes: {"color": Vec4F32}.toTable, -) -let VERTEX_COLORED_MATERIAL* = MaterialType( - name: "vertex color material", - vertexAttributes: { - "position": Vec3F32, - "color": Vec4F32, - }.toTable, -) -let SINGLE_COLOR_MATERIAL* = MaterialType( - name: "single color material", - vertexAttributes: { - "position": Vec3F32, - }.toTable, - attributes: {"color": Vec4F32}.toTable -) -let SINGLE_TEXTURE_MATERIAL* = MaterialType( - name: "single texture material", - vertexAttributes: { - "position": Vec3F32, - "uv": Vec2F32, - }.toTable, - attributes: {"baseTexture": TextureType}.toTable -) -let COLORED_SINGLE_TEXTURE_MATERIAL* = MaterialType( - name: "colored single texture material", - vertexAttributes: { - "position": Vec3F32, - "uv": Vec2F32, - }.toTable, - attributes: {"baseTexture": TextureType, "color": Vec4F32}.toTable -) - -proc `$`*(materialType: MaterialType): string = - var attributes: seq[string] - for key, value in materialType.attributes.pairs: - attributes.add &"{key}: {value}" - return &"""MaterialType '{materialType.name}' | Attributes: {attributes.join(", ")}""" - -proc `$`*(material: MaterialData): string = - var attributes: seq[string] - for key, value in material.attributes.pairs: - attributes.add &"{key}: {value}" - return &"""Material '{material.name}' | Attributes: {attributes.join(", ")}""" - -proc initMaterialData*( - materialType: MaterialType, - name: string, - attributes: Table[string, DataList], -): MaterialData = - var theName = name - if theName == "": - theName = &"material instance of '{materialType}'" - for matName, theType in materialType.attributes.pairs: - assert attributes.contains(matName), &"missing material attribute '{matName}' for {materialType}" - assert attributes[matName].theType == theType - MaterialData( - theType: materialType, - name: theName, - attributes: attributes, - ) - -proc initMaterialData*( - materialType: MaterialType, - name: string = "", - attributes: openArray[(string, DataList)] = @[], -): MaterialData = - var theName = name - if theName == "": - theName = &"material instance of '{materialType}'" - initMaterialData(materialType=materialType, name=theName, attributes=attributes.toTable) - diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/mesh.nim --- a/src/semicongine/mesh.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,538 +0,0 @@ -import std/hashes -import std/options -import std/typetraits -import std/tables -import std/strformat -import std/enumerate -import std/strutils -import std/sequtils - -import ./core -import ./collision -import ./material - -const DEFAULT_POSITION_ATTRIBUTE = "position" - -var instanceCounter* = 0 - -type - MeshIndexType* = enum - None - Tiny # up to 2^8 vertices # TODO: need to check and enable support for this - Small # up to 2^16 vertices - Big # up to 2^32 vertices - MeshObject* = object - name*: string - vertexCount*: int - case indexType*: MeshIndexType - of None: discard - of Tiny: tinyIndices*: seq[array[3, uint8]] - of Small: smallIndices*: seq[array[3, uint16]] - of Big: bigIndices*: seq[array[3, uint32]] - material*: MaterialData - transform*: Mat4 = Unit4 - instanceTransforms*: seq[Mat4] - applyMeshTransformToInstances*: bool = true # if true, the transform attribute for the shader will apply the instance transform AND the mesh transform, to each instance - visible*: bool = true - transformCache: seq[Mat4] - vertexData: Table[string, DataList] - instanceData: Table[string, DataList] - dirtyAttributes: seq[string] - Mesh* = ref MeshObject - -func material*(mesh: MeshObject): MaterialData = - mesh.material - -func `material=`*(mesh: var MeshObject, material: MaterialData) = - for name, theType in material.theType.vertexAttributes: - if mesh.vertexData.contains(name): - assert mesh.vertexData[name].theType == theType, &"{material.theType} expected mesh attribute '{name}' to be '{theType}' but it is {mesh.vertexData[name].theType}" - elif mesh.instanceData.contains(name): - assert mesh.instanceData[name].theType == theType, &"{material.theType} expected mesh attribute '{name}' to be '{theType}' but it is {mesh.instanceData[name].theType}" - else: - assert false, &"Mesh '{mesh.name}' is missing required mesh attribute '{name}: {theType}' for {material.theType}" - mesh.material = material - -func instanceCount*(mesh: MeshObject): int = - mesh.instanceTransforms.len - -func indicesCount*(mesh: MeshObject): int = - ( - case mesh.indexType - of None: 0 - of Tiny: mesh.tinyIndices.len - of Small: mesh.smallIndices.len - of Big: mesh.bigIndices.len - ) * 3 - -func `$`*(mesh: MeshObject): string = - if mesh.indexType == None: - &"Mesh('{mesh.name}', vertexCount: {mesh.vertexCount}, instanceCount: {mesh.instanceCount}, vertexData: {mesh.vertexData.keys().toSeq()}, instanceData: {mesh.instanceData.keys().toSeq()}, indexType: {mesh.indexType}, material: {mesh.material})" - else: - &"Mesh('{mesh.name}', vertexCount: {mesh.vertexCount}, indexCount: {mesh.indicesCount}, instanceCount: {mesh.instanceCount}, vertexData: {mesh.vertexData.keys().toSeq()}, instanceData: {mesh.instanceData.keys().toSeq()}, indexType: {mesh.indexType}, material: {mesh.material})" -func `$`*(mesh: Mesh): string = - $mesh[] - -func vertexAttributes*(mesh: MeshObject): seq[string] = - mesh.vertexData.keys.toSeq - -func instanceAttributes*(mesh: MeshObject): seq[string] = - mesh.instanceData.keys.toSeq - -func attributes*(mesh: MeshObject): seq[string] = - mesh.vertexAttributes & mesh.instanceAttributes - -func hash*(mesh: Mesh): Hash = - hash(cast[ptr MeshObject](mesh)) - -converter toVulkan*(indexType: MeshIndexType): VkIndexType = - case indexType: - of None: VK_INDEX_TYPE_NONE_KHR - of Tiny: VK_INDEX_TYPE_UINT8_EXT - of Small: VK_INDEX_TYPE_UINT16 - of Big: VK_INDEX_TYPE_UINT32 - -proc initVertexAttribute*[T](mesh: var MeshObject, attribute: string, value: seq[T]) = - assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) - mesh.vertexData[attribute] = initDataList(thetype=getDataType[T]()) - mesh.vertexData[attribute].setLen(mesh.vertexCount) - mesh.vertexData[attribute].setValues(value) -proc initVertexAttribute*[T](mesh: var MeshObject, attribute: string, value: T) = - initVertexAttribute(mesh, attribute, newSeqWith(mesh.vertexCount, value)) -proc initVertexAttribute*[T](mesh: var MeshObject, attribute: string) = - initVertexAttribute(mesh=mesh, attribute=attribute, value=default(T)) -proc initVertexAttribute*(mesh: var MeshObject, attribute: string, datatype: DataType) = - assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) - mesh.vertexData[attribute] = initDataList(thetype=datatype) - mesh.vertexData[attribute].setLen(mesh.vertexCount) -proc initVertexAttribute*(mesh: var MeshObject, attribute: string, data: DataList) = - assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) - mesh.vertexData[attribute] = data - - -proc initInstanceAttribute*[T](mesh: var MeshObject, attribute: string, value: seq[T]) = - assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) - mesh.instanceData[attribute] = initDataList(thetype=getDataType[T]()) - mesh.instanceData[attribute].setLen(mesh.instanceCount) - mesh.instanceData[attribute].setValues(value) -proc initInstanceAttribute*[T](mesh: var MeshObject, attribute: string, value: T) = - initInstanceAttribute(mesh, attribute, newSeqWith(mesh.instanceCount, value)) -proc initInstanceAttribute*[T](mesh: var MeshObject, attribute: string) = - initInstanceAttribute(mesh=mesh, attribute=attribute, value=default(T)) -proc initInstanceAttribute*(mesh: var MeshObject, attribute: string, datatype: DataType) = - assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) - mesh.instanceData[attribute] = initDataList(thetype=datatype) - mesh.instanceData[attribute].setLen(mesh.instanceCount) -proc initInstanceAttribute*(mesh: var MeshObject, attribute: string, data: DataList) = - assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute) - mesh.instanceData[attribute] = data - -proc newMesh*( - positions: openArray[Vec3f], - indices: openArray[array[3, uint32|uint16|uint8]], - colors: openArray[Vec4f]=[], - uvs: openArray[Vec2f]=[], - transform: Mat4=Unit4F32, - instanceTransforms: openArray[Mat4]=[Unit4F32], - material=EMPTY_MATERIAL.initMaterialData(), - autoResize=true, - name: string="" -): Mesh = - assert colors.len == 0 or colors.len == positions.len - assert uvs.len == 0 or uvs.len == positions.len - var theName = name - if theName == "": - theName = &"mesh-{instanceCounter}" - inc instanceCounter - - # determine index type (uint8, uint16, uint32) - var indexType = None - if indices.len > 0: - indexType = Big - if autoResize and uint32(positions.len) < uint32(high(uint8)) and false: # TODO: check feature support - indexType = Tiny - elif autoResize and uint32(positions.len) < uint32(high(uint16)): - indexType = Small - - result = Mesh( - name: theName, - indexType: indexType, - vertexCount: positions.len, - instanceTransforms: @instanceTransforms, - transform: transform, - material: material - ) - - result[].initVertexAttribute(DEFAULT_POSITION_ATTRIBUTE , positions.toSeq) - if colors.len > 0: result[].initVertexAttribute("color", colors.toSeq) - if uvs.len > 0: result[].initVertexAttribute("uv", uvs.toSeq) - - # assert all indices are valid - for i in indices: - assert int(i[0]) < result[].vertexCount - assert int(i[1]) < result[].vertexCount - assert int(i[2]) < result[].vertexCount - - # cast index values to appropiate type - if result[].indexType == Tiny and uint32(positions.len) < uint32(high(uint8)) and false: # TODO: check feature support - for i, tri in enumerate(indices): - result[].tinyIndices.add [uint8(tri[0]), uint8(tri[1]), uint8(tri[2])] - elif result[].indexType == Small and uint32(positions.len) < uint32(high(uint16)): - for i, tri in enumerate(indices): - result[].smallIndices.add [uint16(tri[0]), uint16(tri[1]), uint16(tri[2])] - elif result[].indexType == Big: - for i, tri in enumerate(indices): - result[].bigIndices.add [uint32(tri[0]), uint32(tri[1]), uint32(tri[2])] - -proc newMesh*( - positions: openArray[Vec3f], - colors: openArray[Vec4f]=[], - uvs: openArray[Vec2f]=[], - transform: Mat4=Unit4F32, - instanceTransforms: openArray[Mat4]=[Unit4F32], - material=EMPTY_MATERIAL.initMaterialData(), - name: string="", -): Mesh = - newMesh( - positions=positions, - indices=newSeq[array[3, uint16]](), - colors=colors, - uvs=uvs, - transform=transform, - instanceTransforms=instanceTransforms, - material=material, - name=name, - ) - -func attributeSize*(mesh: MeshObject, attribute: string): int = - if mesh.vertexData.contains(attribute): - mesh.vertexData[attribute].size - elif mesh.instanceData.contains(attribute): - mesh.instanceData[attribute].size - else: - 0 - -func attributeType*(mesh: MeshObject, attribute: string): DataType = - if mesh.vertexData.contains(attribute): - mesh.vertexData[attribute].theType - elif mesh.instanceData.contains(attribute): - mesh.instanceData[attribute].theType - else: - raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") - -func indexSize*(mesh: MeshObject): int = - case mesh.indexType - of None: 0 - of Tiny: mesh.tinyIndices.len * sizeof(get(genericParams(typeof(mesh.tinyIndices)), 0)) - of Small: mesh.smallIndices.len * sizeof(get(genericParams(typeof(mesh.smallIndices)), 0)) - of Big: mesh.bigIndices.len * sizeof(get(genericParams(typeof(mesh.bigIndices)), 0)) - -func rawData[T: seq](value: T): (pointer, int) = - (pointer(addr(value[0])), sizeof(get(genericParams(typeof(value)), 0)) * value.len) - -func getRawIndexData*(mesh: MeshObject): (pointer, int) = - case mesh.indexType: - of None: raise newException(Exception, "Trying to get index data for non-indexed mesh") - of Tiny: rawData(mesh.tinyIndices) - of Small: rawData(mesh.smallIndices) - of Big: rawData(mesh.bigIndices) - -func getRawData*(mesh: var MeshObject, attribute: string): (pointer, int) = - if mesh.vertexData.contains(attribute): - mesh.vertexData[attribute].getRawData() - elif mesh.instanceData.contains(attribute): - mesh.instanceData[attribute].getRawData() - else: - raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") - -proc getAttribute[T: GPUType|int|uint|float](mesh: MeshObject, attribute: string): ref seq[T] = - if mesh.vertexData.contains(attribute): - getValues[T](mesh.vertexData[attribute]) - elif mesh.instanceData.contains(attribute): - getValues[T](mesh.instanceData[attribute]) - else: - raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") - -proc getAttribute[T: GPUType|int|uint|float](mesh: MeshObject, attribute: string, i: int): T = - if mesh.vertexData.contains(attribute): - getValue[T](mesh.vertexData[attribute], i) - elif mesh.instanceData.contains(attribute): - getValue[T](mesh.instanceData[attribute], i) - else: - raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") - -template `[]`*(mesh: MeshObject, attribute: string, t: typedesc): ref seq[t] = - getAttribute[t](mesh, attribute) -template `[]`*(mesh: Mesh, attribute: string, t: typedesc): ref seq[t] = - getAttribute[t](mesh[], attribute) -template `[]`*(mesh: MeshObject, attribute: string, i: int, t: typedesc): untyped = - getAttribute[t](mesh, attribute, i) -template `[]`*(mesh: Mesh, attribute: string, i: int, t: typedesc): untyped = - getAttribute[t](mesh[], attribute, i) - -proc updateAttributeData[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, data: DataList) = - if mesh.vertexData.contains(attribute): - assert data.len == mesh.vertexCount - assert data.theType == mesh.vertexData[attribute].theType - mesh.vertexData[attribute] = data - elif mesh.instanceData.contains(attribute): - assert data.len == mesh.instanceCount - assert data.theType == mesh.instanceData[attribute].theType - mesh.instanceData[attribute] = data - else: - raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") - if not mesh.dirtyAttributes.contains(attribute): - mesh.dirtyAttributes.add attribute - -proc updateAttributeData[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, data: seq[T]) = - if mesh.vertexData.contains(attribute): - assert data.len == mesh.vertexCount - setValues(mesh.vertexData[attribute], data) - elif mesh.instanceData.contains(attribute): - assert data.len == mesh.instanceCount - setValues(mesh.instanceData[attribute], data) - else: - raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") - if not mesh.dirtyAttributes.contains(attribute): - mesh.dirtyAttributes.add attribute - -proc updateAttributeData[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, i: int, value: T) = - if mesh.vertexData.contains(attribute): - assert i < mesh.vertexData[attribute].len - setValue(mesh.vertexData[attribute], i, value) - elif mesh.instanceData.contains(attribute): - assert i < mesh.instanceData[attribute].len - setValue(mesh.instanceData[attribute], i, value) - else: - raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") - if not mesh.dirtyAttributes.contains(attribute): - mesh.dirtyAttributes.add attribute - -proc `[]=`*[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, data: DataList) = - updateAttributeData[T](mesh, attribute, data) -proc `[]=`*[T: GPUType|int|uint|float](mesh: Mesh, attribute: string, data: DataList) = - updateAttributeData[t](mesh[], attribute, data) - -proc `[]=`*[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, data: seq[T]) = - updateAttributeData[T](mesh, attribute, data) -proc `[]=`*[T: GPUType|int|uint|float](mesh: Mesh, attribute: string, data: seq[T]) = - updateAttributeData[t](mesh[], attribute, data) - -proc `[]=`*[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, value: T) = - updateAttributeData[T](mesh, attribute, newSeqWith(mesh.vertexCount, value)) -proc `[]=`*[T: GPUType|int|uint|float](mesh: Mesh, attribute: string, value: T) = - updateAttributeData[T](mesh[], attribute, newSeqWith(mesh.vertexCount, value)) - -proc `[]=`*[T: GPUType|int|uint|float](mesh: var MeshObject, attribute: string, i: int, value: T) = - updateAttributeData[T](mesh, attribute, i, value) -proc `[]=`*[T: GPUType|int|uint|float](mesh: Mesh, attribute: string, i: int, value: T) = - updateAttributeData[T](mesh[], attribute, i, value) - -proc removeAttribute*(mesh: var MeshObject, attribute: string) = - if mesh.vertexData.contains(attribute): - mesh.vertexData.del(attribute) - elif mesh.instanceData.contains(attribute): - mesh.instanceData.del(attribute) - else: - raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") - -proc appendIndicesData*(mesh: var MeshObject, v1, v2, v3: int) = - case mesh.indexType - of None: raise newException(Exception, "Mesh does not support indexed data") - of Tiny: mesh.tinyIndices.add([uint8(v1), uint8(v2), uint8(v3)]) - of Small: mesh.smallIndices.add([uint16(v1), uint16(v2), uint16(v3)]) - of Big: mesh.bigIndices.add([uint32(v1), uint32(v2), uint32(v3)]) - -proc updateInstanceTransforms*(mesh: var MeshObject, attribute: string) = - var currentTransforms: seq[Mat4] - if mesh.applyMeshTransformToInstances: - currentTransforms = mesh.instanceTransforms.mapIt(mesh.transform * it) - else: - currentTransforms = mesh.instanceTransforms - if currentTransforms != mesh.transformCache: - mesh[attribute] = currentTransforms - mesh.transformCache = currentTransforms - -proc renameAttribute*(mesh: var MeshObject, oldname, newname: string) = - if mesh.vertexData.contains(oldname): - mesh.vertexData[newname] = mesh.vertexData[oldname] - mesh.vertexData.del oldname - elif mesh.instanceData.contains(oldname): - mesh.instanceData[newname] = mesh.vertexData[oldname] - mesh.instanceData.del oldname - else: - raise newException(Exception, &"Attribute {oldname} is not defined for mesh {mesh}") - -func dirtyAttributes*(mesh: MeshObject): seq[string] = - mesh.dirtyAttributes - -proc clearDirtyAttributes*(mesh: var MeshObject) = - mesh.dirtyAttributes.reset - -proc transform*[T: GPUType](mesh: var MeshObject, attribute: string, transform: Mat4) = - if mesh.vertexData.contains(attribute): - for i in 0 ..< mesh.vertexData[attribute].len: - setValue(mesh.vertexData[attribute], i, transform * getValue[T](mesh.vertexData[attribute], i)) - elif mesh.instanceData.contains(attribute): - for i in 0 ..< mesh.instanceData[attribute].len: - setValue(mesh.instanceData[attribute], i, transform * getValue[T](mesh.vertexData[attribute], i)) - else: - raise newException(Exception, &"Attribute {attribute} is not defined for mesh {mesh}") - -proc applyTransformToVertices*(mesh: var MeshObject, positionAttribute=DEFAULT_POSITION_ATTRIBUTE) = - for i in 0 ..< mesh.vertexData[positionAttribute].len: - setValue(mesh.vertexData[positionAttribute], i, mesh.transform * getValue[Vec3f](mesh.vertexData[positionAttribute], i)) - mesh.transform = Unit4 - - -func getCollisionPoints*(mesh: MeshObject, positionAttribute=DEFAULT_POSITION_ATTRIBUTE): seq[Vec3f] = - for p in mesh[positionAttribute, Vec3f][]: - result.add mesh.transform * p - -func getCollider*(mesh: MeshObject, positionAttribute=DEFAULT_POSITION_ATTRIBUTE): Collider = - return mesh.getCollisionPoints(positionAttribute).calculateCollider(Points) - -proc asNonIndexedMesh*(mesh: MeshObject): MeshObject = - if mesh.indexType == None: - return mesh - - result = MeshObject( - vertexCount: mesh.indicesCount, - indexType: None, - transform: mesh.transform, - instanceTransforms: mesh.instanceTransforms, - visible: mesh.visible, - material: mesh.material - ) - for attribute, datalist in mesh.vertexData.pairs: - result.initVertexAttribute(attribute, datalist.theType) - for attribute, datalist in mesh.instanceData.pairs: - result.instanceData[attribute] = datalist.copy() - var i = 0 - case mesh.indexType - of Tiny: - for indices in mesh.tinyIndices: - for attribute, value in mesh.vertexData.pairs: - result.vertexData[attribute].appendFrom(i, mesh.vertexData[attribute], int(indices[0])) - result.vertexData[attribute].appendFrom(i + 1, mesh.vertexData[attribute], int(indices[1])) - result.vertexData[attribute].appendFrom(i + 2, mesh.vertexData[attribute], int(indices[2])) - i += 3 - of Small: - for indices in mesh.smallIndices: - for attribute, value in mesh.vertexData.pairs: - result.vertexData[attribute].appendFrom(i, value, int(indices[0])) - result.vertexData[attribute].appendFrom(i + 1, value, int(indices[1])) - result.vertexData[attribute].appendFrom(i + 2, value, int(indices[2])) - i += 3 - of Big: - for indices in mesh.bigIndices: - for attribute, value in mesh.vertexData.pairs: - result.vertexData[attribute].appendFrom(i, mesh.vertexData[attribute], int(indices[0])) - result.vertexData[attribute].appendFrom(i + 1, mesh.vertexData[attribute], int(indices[1])) - result.vertexData[attribute].appendFrom(i + 2, mesh.vertexData[attribute], int(indices[2])) - i += 3 - else: - discard - return result - - -# GENERATORS ============================================================================ - -proc rect*(width=1'f32, height=1'f32, color="ffffffff", material=EMPTY_MATERIAL.initMaterialData()): Mesh = - result = Mesh( - vertexCount: 4, - instanceTransforms: @[Unit4F32], - indexType: Small, - smallIndices: @[[0'u16, 1'u16, 2'u16], [2'u16, 3'u16, 0'u16]], - name: &"rect-{instanceCounter}", - material: material, - ) - inc instanceCounter - - let - half_w = width / 2 - half_h = height / 2 - pos = @[newVec3f(-half_w, -half_h), newVec3f( half_w, -half_h), newVec3f( half_w, half_h), newVec3f(-half_w, half_h)] - c = toRGBA(color) - - result[].initVertexAttribute(DEFAULT_POSITION_ATTRIBUTE, pos) - result[].initVertexAttribute("color", @[c, c, c, c]) - result[].initVertexAttribute("uv", @[newVec2f(0, 0), newVec2f(1, 0), newVec2f(1, 1), newVec2f(0, 1)]) - -proc tri*(width=1'f32, height=1'f32, color="ffffffff", material=EMPTY_MATERIAL.initMaterialData()): Mesh = - result = Mesh( - vertexCount: 3, - instanceTransforms: @[Unit4F32], - name: &"tri-{instanceCounter}", - material: material, - ) - inc instanceCounter - let - half_w = width / 2 - half_h = height / 2 - colorVec = toRGBA(color) - - result[].initVertexAttribute(DEFAULT_POSITION_ATTRIBUTE, @[newVec3f(0, -half_h), newVec3f( half_w, half_h), newVec3f(-half_w, half_h)]) - result[].initVertexAttribute("color", @[colorVec, colorVec, colorVec]) - -proc circle*(width=1'f32, height=1'f32, nSegments=12, color="ffffffff", material=EMPTY_MATERIAL.initMaterialData()): Mesh = - assert nSegments >= 3 - result = Mesh( - vertexCount: 3 + nSegments, - instanceTransforms: @[Unit4F32], - indexType: Small, - name: &"circle-{instanceCounter}", - material: material, - ) - inc instanceCounter - - let - half_w = width / 2 - half_h = height / 2 - c = toRGBA(color) - step = (2'f32 * PI) / float32(nSegments) - var - pos = @[newVec3f(0, 0), newVec3f(0, half_h)] - col = @[c, c] - for i in 0 .. nSegments: - pos.add newVec3f(cos(float32(i) * step) * half_w, sin(float32(i) * step) * half_h) - col.add c - result[].smallIndices.add [uint16(0), uint16(i + 1), uint16(i + 2)] - - result[].initVertexAttribute(DEFAULT_POSITION_ATTRIBUTE, pos) - result[].initVertexAttribute("color", col) - -# MESH TREES ============================================================================= - -type - MeshTree* = ref object - mesh*: Mesh - transform*: Mat4 = Unit4F32 - children*: seq[MeshTree] - -func toStringRec*(tree: MeshTree, theindent=0): seq[string] = - if tree.mesh.isNil: - result.add "*" - else: - result.add indent($tree.mesh, theindent) - for child in tree.children: - result.add child.toStringRec(theindent + 4) - -func `$`*(tree: MeshTree): string = - toStringRec(tree).join("\n") - - -proc toSeq*(tree: MeshTree): seq[Mesh] = - var queue = @[tree] - while queue.len > 0: - var current = queue.pop - if not current.mesh.isNil: - result.add current.mesh - queue.add current.children - -proc updateTransforms*(tree: MeshTree, parentTransform=Unit4F32) = - let currentTransform = parentTransform * tree.transform - if not tree.mesh.isNil: - tree.mesh.transform = currentTransform - for child in tree.children: - child.updateTransforms(currentTransform) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/noise.nim --- a/src/semicongine/noise.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -import hashes -import math - -import ./core/vector - - -proc randomGradient(pos: Vec2f, seed: int32 = 0): Vec2f = - let randomAngle: float32 = TAU * (float32(int(hash((pos.x, pos.y, seed)))) / float32(high(int))) - return newVec2f(cos(randomAngle), sin(randomAngle)) - -proc interpolate(a: float32, b: float32, weight: float32): float32 = - # with Smootherstep - (b - a) * ((weight * (weight * 6.0 - 15.0) + 10.0) * weight * weight * weight) + a; - -proc perlin*(pos: Vec2f, seed: int32 = 0): float32 = - let - # grid coordinates around target point - topleft = newVec2f(trunc(pos.x), trunc(pos.y)) - topright = topleft + newVec2f(1, 0) - bottomleft = topleft + newVec2f(0, 1) - bottomright = topleft + newVec2f(1, 1) - # products for weights - topleft_dot = topleft.randomGradient(seed).dot((pos - topleft)) - topright_dot = topright.randomGradient(seed).dot((pos - topright)) - bottomleft_dot = bottomleft.randomGradient(seed).dot((pos - bottomleft)) - bottomright_dot = bottomright.randomGradient(seed).dot((pos - bottomright)) - xinterpol = pos.x - topleft.x - yinterpol = pos.y - topleft.y - - return interpolate( - interpolate(topleft_dot, bottomleft_dot, yinterpol), - interpolate(topright_dot, bottomright_dot, yinterpol), - xinterpol - ) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/audio.nim --- a/src/semicongine/platform/audio.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -when defined(linux): - include ./linux/audio -elif defined(windows): - include ./windows/audio - -export audio diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/linux/audio.nim --- a/src/semicongine/platform/linux/audio.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -import ../../core - -# alsa API -type - OpenMode*{.size: sizeof(culong).} = enum - SND_PCM_BLOCK = 0x00000000 # added by semicongine, for clarity - SND_PCM_NONBLOCK = 0x00000001 - StreamMode* {.size: sizeof(cint).} = enum - SND_PCM_STREAM_PLAYBACK = 0 - AccessMode*{.size: sizeof(cint).} = enum - SND_PCM_ACCESS_RW_INTERLEAVED = 3 - PCMFormat*{.size: sizeof(cint).} = enum - SND_PCM_FORMAT_S16_LE = 2 - snd_pcm_p* = ptr object - snd_pcm_hw_params_p* = ptr object - snd_pcm_uframes_t* = culong - snd_pcm_sframes_t* = clong -{.pragma: alsafunc, importc, cdecl, dynlib: "libasound.so.2" .} -proc snd_pcm_open*(pcm_ref: ptr snd_pcm_p, name: cstring, streamMode: StreamMode, openmode: OpenMode): cint {.alsafunc.} -proc snd_pcm_close*(pcm: snd_pcm_p): cint {.alsafunc.} -proc snd_pcm_hw_params_malloc*(hw_params_ptr: ptr snd_pcm_hw_params_p): cint {.alsafunc.} -proc snd_pcm_hw_params_free*(hw_params: snd_pcm_hw_params_p) {.alsafunc.} -proc snd_pcm_hw_params_any*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p): cint {.alsafunc.} -proc snd_pcm_hw_params_set_access*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, mode: AccessMode): cint {.alsafunc.} -proc snd_pcm_hw_params_set_format*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, format: PCMFormat): cint {.alsafunc.} -proc snd_pcm_hw_params_set_channels*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, val: cuint): cint {.alsafunc.} -proc snd_pcm_hw_params_set_buffer_size*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, size: snd_pcm_uframes_t): cint {.alsafunc.} -proc snd_pcm_hw_params_set_rate*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p, val: cuint, dir: cint): cint {.alsafunc.} -proc snd_pcm_hw_params*(pcm: snd_pcm_p, params: snd_pcm_hw_params_p): cint {.alsafunc.} -proc snd_pcm_writei*(pcm: snd_pcm_p, buffer: pointer, size: snd_pcm_uframes_t): snd_pcm_sframes_t {.alsafunc.} -proc snd_pcm_recover*(pcm: snd_pcm_p, err: cint, silent: cint): cint {.alsafunc.} - -template checkAlsaResult*(call: untyped) = - let value = call - if value < 0: - raise newException(Exception, "Alsa error: " & astToStr(call) & - " returned " & $value) - -# required for engine: - -type - NativeSoundDevice* = object - handle: snd_pcm_p - buffers: seq[ptr SoundData] - -proc openSoundDevice*(sampleRate: uint32, buffers: seq[ptr SoundData]): NativeSoundDevice = - var hw_params: snd_pcm_hw_params_p = nil - checkAlsaResult snd_pcm_open(addr result.handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_BLOCK) - - # hw parameters, quiet a bit of hardcoding here - checkAlsaResult snd_pcm_hw_params_malloc(addr hw_params) - checkAlsaResult snd_pcm_hw_params_any(result.handle, hw_params) - checkAlsaResult snd_pcm_hw_params_set_access(result.handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) - checkAlsaResult snd_pcm_hw_params_set_format(result.handle, hw_params, SND_PCM_FORMAT_S16_LE) - checkAlsaResult snd_pcm_hw_params_set_rate(result.handle, hw_params, sampleRate, 0) - checkAlsaResult snd_pcm_hw_params_set_channels(result.handle, hw_params, 2) - checkAlsaResult snd_pcm_hw_params_set_buffer_size(result.handle, hw_params, snd_pcm_uframes_t(buffers[0][].len)) - checkAlsaResult snd_pcm_hw_params(result.handle, hw_params) - snd_pcm_hw_params_free(hw_params) - result.buffers = buffers - -proc writeSoundData*(soundDevice: NativeSoundDevice, buffer: int) = - var ret = snd_pcm_writei(soundDevice.handle, addr soundDevice.buffers[buffer][][0], snd_pcm_uframes_t(soundDevice.buffers[buffer][].len)) - if ret < 0: - checkAlsaResult snd_pcm_recover(soundDevice.handle, cint(ret), 0) - -proc closeSoundDevice*(soundDevice: NativeSoundDevice) = - discard snd_pcm_close(soundDevice.handle) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/linux/surface.nim --- a/src/semicongine/platform/linux/surface.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -import ../../core -import ../../platform/window - -proc createNativeSurface*(instance: VkInstance, window: NativeWindow): VkSurfaceKHR = - assert instance.valid - var surfaceCreateInfo = VkXlibSurfaceCreateInfoKHR( - sType: VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, - dpy: cast[ptr vulkanapi.Display](window.display), - window: cast[vulkanapi.Window](window.window), - ) - checkVkResult vkCreateXlibSurfaceKHR(instance, addr(surfaceCreateInfo), nil, addr(result)) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/linux/symkey_map.nim --- a/src/semicongine/platform/linux/symkey_map.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -import std/tables -export tables - -import x11/x - - -import ../../events - -# got values (keycodes) from xev -const KeyTypeMap* = { - 9: Escape, 67: F1, 68: F2, 69: F3, 70: F4, 71: F5, 72: F6, 73: F7, 74: F8, - 75: F9, 76: F10, 95: F11, 96: F12, - 49: NumberRowExtra1, 10: `1`, 11: `2`, 12: `3`, 13: `4`, 14: `5`, 15: `6`, - 16: `7`, 17: `8`, 18: `9`, 19: `0`, 20: NumberRowExtra2, 21: NumberRowExtra3, - 24: Q, 25: W, 26: E, 27: R, 28: T, 29: Y, 30: U, 31: I, 32: O, 33: P, 38: A, - 39: S, 40: D, 41: Key.F, 42: G, 43: H, 44: J, 45: K, 46: L, 52: Z, 53: X, - 54: C, 55: V, 56: B, 57: N, 58: M, - - 23: Tab, 66: CapsLock, 50: ShiftL, 62: ShiftR, 37: CtrlL, 105: CtrlR, - 133: SuperL, 134: SuperR, - 64: AltL, 108: AltR, - 65: Space, 36: Enter, 22: Backspace, - 34: LetterRow1Extra1, 35: LetterRow1Extra2, - 47: LetterRow2Extra1, 48: LetterRow2Extra2, 51: LetterRow2Extra3, - 59: LetterRow3Extra1, 60: LetterRow3Extra2, 61: LetterRow3Extra3, - 111: Up, 116: Down, 113: Left, 114: Right, - 112: PageUp, 117: PageDown, 110: Home, 115: End, 118: Insert, 119: Delete, - 107: PrintScreen, 78: ScrollLock, 127: Pause, -}.toTable - -const MouseButtonTypeMap* = { - Button1: MouseButton.Mouse1, - Button2: MouseButton.Mouse2, - Button3: MouseButton.Mouse3, -}.toTable diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/linux/vulkanExtensions.nim --- a/src/semicongine/platform/linux/vulkanExtensions.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -const REQUIRED_PLATFORM_EXTENSIONS* = @["VK_KHR_xlib_surface"] diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/linux/window.nim --- a/src/semicongine/platform/linux/window.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +0,0 @@ -import std/options -import std/tables -import std/strformat -import std/logging - -import - x11/xlib, - x11/xutil, - x11/keysym, - x11/x, - x11/xkblib - -import ../../core -import ../../events - -import ./symkey_map - -export keysym - -var deleteMessage*: Atom - -type - NativeWindow* = object - display*: ptr xlib.Display - window*: x.Window - emptyCursor: Cursor - -template checkXlibResult*(call: untyped) = - let value = call - if value == 0: - raise newException(Exception, "Xlib error: " & astToStr(call) & - " returned " & $value) - -proc XErrorLogger(display: PDisplay, event: PXErrorEvent): cint {.cdecl.} = - error &"Xlib: {event[]}" - -proc createWindow*(title: string): NativeWindow = - checkXlibResult XInitThreads() - let display = XOpenDisplay(nil) - if display == nil: - quit "Failed to open display" - discard XSetErrorHandler(XErrorLogger) - - let rootWindow = display.XDefaultRootWindow() - discard display.XkbSetDetectableAutoRepeat(true, nil) - var - attribs: XWindowAttributes - width = cuint(800) - height = cuint(600) - checkXlibResult display.XGetWindowAttributes(rootWindow, addr(attribs)) - - var attrs = XSetWindowAttributes() - let window = XCreateWindow( - display, - rootWindow, - (attribs.width - cint(width)) div 2, (attribs.height - cint(height)) div 2, - width, height, - 0, - CopyFromParent, - InputOutput, - cast[PVisual](CopyFromParent), - 0, # CWOverrideRedirect, - addr attrs, - # foregroundColor, backgroundColor - ) - checkXlibResult XSetStandardProperties(display, window, title, "window", 0, nil, 0, nil) - checkXlibResult XSelectInput(display, window, PointerMotionMask or ButtonPressMask or ButtonReleaseMask or KeyPressMask or KeyReleaseMask or ExposureMask) - checkXlibResult XMapWindow(display, window) - - deleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", XBool(false)) - checkXlibResult XSetWMProtocols(display, window, addr(deleteMessage), 1) - - var data = "\0".cstring - var pixmap = display.XCreateBitmapFromData(window, data, 1, 1) - var color: XColor - var empty_cursor = display.XCreatePixmapCursor(pixmap, pixmap, addr(color), addr(color), 0, 0) - checkXlibResult display.XFreePixmap(pixmap) - return NativeWindow(display: display, window: window, emptyCursor: empty_cursor) - -proc fullscreen*(window: var NativeWindow, enable: bool) = - var - wm_state = window.display.XInternAtom("_NET_WM_STATE", 0) - wm_fullscreen = window.display.XInternAtom("_NET_WM_STATE_FULLSCREEN", 0) - var - xev: XEvent - xev.xclient = XClientMessageEvent( - message_type: wm_state, - format: 32, - window: window.window, - data: XClientMessageData( - l: [ - int(not enable) xor 1, - clong(wm_fullscreen), - 0, - 0, - 0 - ] - ) - ) - xev.theType = ClientMessage - - checkXlibResult window.display.XSendEvent( - window.display.DefaultRootWindow(), - 0, - SubstructureRedirectMask or SubstructureNotifyMask, - addr xev - ) - checkXlibResult window.display.XFlush() - -proc hideSystemCursor*(window: NativeWindow) = - checkXlibResult XDefineCursor(window.display, window.window, window.emptyCursor) - checkXlibResult window.display.XFlush() - -proc showSystemCursor*(window: NativeWindow) = - checkXlibResult XUndefineCursor(window.display, window.window) - checkXlibResult window.display.XFlush() - -proc destroy*(window: NativeWindow) = - checkXlibResult window.display.XFreeCursor(window.emptyCursor) - checkXlibResult window.display.XDestroyWindow(window.window) - discard window.display.XCloseDisplay() # always returns 0 - -proc size*(window: NativeWindow): (int, int) = - var attribs: XWindowAttributes - checkXlibResult XGetWindowAttributes(window.display, window.window, addr(attribs)) - return (int(attribs.width), int(attribs.height)) - -proc pendingEvents*(window: NativeWindow): seq[Event] = - var event: XEvent - while window.display.XPending() > 0: - discard window.display.XNextEvent(addr(event)) - case event.theType - of ClientMessage: - if cast[Atom](event.xclient.data.l[0]) == deleteMessage: - result.add(Event(eventType: Quit)) - of KeyPress: - let keyevent = cast[PXKeyEvent](addr(event)) - let xkey = int(keyevent.keycode) - result.add Event(eventType: KeyPressed, key: KeyTypeMap.getOrDefault(xkey, Key.UNKNOWN)) - of KeyRelease: - let keyevent = cast[PXKeyEvent](addr(event)) - let xkey = int(keyevent.keycode) - result.add Event(eventType: KeyReleased, key: KeyTypeMap.getOrDefault(xkey, Key.UNKNOWN)) - of ButtonPress: - let button = int(cast[PXButtonEvent](addr(event)).button) - if button == Button4: - result.add Event(eventType: MouseWheel, amount: 1'f32) - elif button == Button5: - result.add Event(eventType: MouseWheel, amount: -1'f32) - else: - result.add Event(eventType: MousePressed, button: MouseButtonTypeMap.getOrDefault(button, MouseButton.UNKNOWN)) - of ButtonRelease: - let button = int(cast[PXButtonEvent](addr(event)).button) - result.add Event(eventType: MouseReleased, button: MouseButtonTypeMap.getOrDefault(button, MouseButton.UNKNOWN)) - of MotionNotify: - let motion = cast[PXMotionEvent](addr(event)) - result.add Event(eventType: MouseMoved, x: motion.x, y: motion.y) - of ConfigureNotify, Expose: - result.add Event(eventType: ResizedWindow) - else: - discard - - -proc getMousePosition*(window: NativeWindow): Option[Vec2f] = - var - root: x.Window - win: x.Window - rootX: cint - rootY: cint - winX: cint - winY: cint - mask: cuint - onscreen = XQueryPointer( - window.display, - window.window, - addr(root), - addr(win), - addr(rootX), - addr(rootY), - addr(winX), - addr(winY), - addr(mask), - ) - if onscreen != 0: - result = some(Vec2f([float32(winX), float32(winY)])) - diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/surface.nim --- a/src/semicongine/platform/surface.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -when defined(linux): - import ../platform/linux/surface -elif defined(windows): - import ../platform/windows/surface - -export surface diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/vulkanExtensions.nim --- a/src/semicongine/platform/vulkanExtensions.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -when defined(linux): - include ./linux/vulkanExtensions -elif defined(windows): - include ./windows/vulkanExtensions - -export vulkanExtensions diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/window.nim --- a/src/semicongine/platform/window.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -when defined(linux): - include ./linux/window -elif defined(windows): - include ./windows/window - -export window diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/windows/audio.nim --- a/src/semicongine/platform/windows/audio.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -import winim -import winim/extra - -import ../../core/audiotypes - -template checkWinMMResult*(call: untyped) = - let value = call - if value < 0: - raise newException(Exception, "Windows multimedia error: " & astToStr(call) & - " returned " & $value) -type - NativeSoundDevice* = object - handle: HWAVEOUT - buffers: seq[WAVEHDR] - -proc openSoundDevice*(sampleRate: uint32, buffers: seq[ptr SoundData]): NativeSoundDevice = - var format = WAVEFORMATEX( - wFormatTag: WAVE_FORMAT_PCM, - nChannels: 2, - nSamplesPerSec: DWORD(sampleRate), - nAvgBytesPerSec: DWORD(sampleRate) * 4, - nBlockAlign: 4, - wBitsPerSample: 16, - cbSize: 0, - ) - checkWinMMResult waveOutOpen(addr result.handle, WAVE_MAPPER, addr format, DWORD_PTR(0), DWORD_PTR(0), CALLBACK_NULL) - - for i in 0 ..< buffers.len: - result.buffers.add WAVEHDR( - lpData: cast[cstring](addr buffers[i][][0]), - dwBufferLength: DWORD(buffers[i][].len * sizeof(Sample)), - dwLoops: 1, - ) - for i in 0 ..< result.buffers.len: - checkWinMMResult waveOutPrepareHeader(result.handle, addr result.buffers[i], UINT(sizeof(WAVEHDR))) - checkWinMMResult waveOutWrite(result.handle, addr result.buffers[i], UINT(sizeof(WAVEHDR))) - -proc writeSoundData*(soundDevice: var NativeSoundDevice, buffer: int) = - while (soundDevice.buffers[buffer].dwFlags and WHDR_DONE) == 0: - echo "" # ugly solution to prevent code elimination, need to find a nicer solution - checkWinMMResult waveOutWrite(soundDevice.handle, addr soundDevice.buffers[buffer], UINT(sizeof(WAVEHDR))) - -proc closeSoundDevice*(soundDevice: var NativeSoundDevice) = - for i in 0 ..< soundDevice.buffers.len: - discard waveOutUnprepareHeader(soundDevice.handle, addr soundDevice.buffers[i], UINT(sizeof(WAVEHDR))) - waveOutClose(soundDevice.handle) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/windows/surface.nim --- a/src/semicongine/platform/windows/surface.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -import ../../core -import ../../platform/window - -proc createNativeSurface*(instance: VkInstance, window: NativeWindow): VkSurfaceKHR = - assert instance.valid - var surfaceCreateInfo = VkWin32SurfaceCreateInfoKHR( - sType: VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, - hinstance: cast[HINSTANCE](window.hinstance), - hwnd: cast[HWND](window.hwnd), - ) - checkVkResult vkCreateWin32SurfaceKHR(instance, addr(surfaceCreateInfo), nil, addr(result)) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/windows/virtualkey_map.nim --- a/src/semicongine/platform/windows/virtualkey_map.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -import std/tables -export tables - -import winim/core - -import ../../events - -const KeyTypeMap* = { - VK_ESCAPE: Key.Escape, VK_F1: F1, VK_F2: F2, VK_F3: F3, VK_F4: F4, VK_F5: F5, - VK_F6: F6, VK_F7: F7, VK_F8: F8, VK_F9: F9, VK_F10: F10, VK_F11: F11, - VK_F12: F12, - VK_OEM_3: NumberRowExtra1, int('0'): `0`, int('1'): `1`, int('2'): `2`, int( - '3'): `3`, int('4'): `4`, int('5'): `5`, int('6'): `6`, int('7'): `7`, - int('8'): `8`, int('9'): `9`, VK_OEM_MINUS: NumberRowExtra2, - VK_OEM_PLUS: NumberRowExtra3, - int('A'): A, int('B'): B, int('C'): C, int('D'): D, int('E'): E, int('F'): F, - int('G'): G, int('H'): H, int('I'): I, int('J'): J, int('K'): K, int( - 'L'): L, int('M'): M, int('N'): N, int('O'): O, int('P'): P, int('Q'): Q, - int('R'): R, int('S'): S, int('T'): T, int('U'): U, int('V'): V, int( - 'W'): W, int('X'): X, int('Y'): Y, int('Z'): Z, - VK_TAB: Tab, VK_CAPITAL: CapsLock, VK_LSHIFT: ShiftL, VK_SHIFT: ShiftL, - VK_RSHIFT: ShiftR, VK_LCONTROL: CtrlL, VK_CONTROL: CtrlL, - VK_RCONTROL: CtrlR, VK_LWIN: SuperL, VK_RWIN: SuperR, VK_LMENU: AltL, - VK_RMENU: AltR, VK_SPACE: Space, VK_RETURN: Enter, VK_BACK: Backspace, - VK_OEM_4: LetterRow1Extra1, VK_OEM_6: LetterRow1Extra2, - VK_OEM_5: LetterRow2Extra3, - VK_OEM_1: LetterRow2Extra1, VK_OEM_7: LetterRow2Extra2, - VK_OEM_COMMA: LetterRow3Extra1, VK_OEM_PERIOD: LetterRow3Extra2, - VK_OEM_2: LetterRow3Extra3, - VK_UP: Up, VK_DOWN: Down, VK_LEFT: Left, VK_RIGHT: Right, - VK_PRIOR: PageUp, VK_NEXT: PageDown, VK_HOME: Home, VK_END: End, - VK_INSERT: Insert, VK_DELETE: Key.Delete, -}.toTable diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/windows/vulkanExtensions.nim --- a/src/semicongine/platform/windows/vulkanExtensions.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -const REQUIRED_PLATFORM_EXTENSIONS* = @["VK_KHR_win32_surface"] diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/platform/windows/window.nim --- a/src/semicongine/platform/windows/window.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -import std/options -import winim - -import ../../core/vector -import ./virtualkey_map -import ../../events - -type - NativeWindow* = object - hinstance*: HINSTANCE - hwnd*: HWND - g_wpPrev: WINDOWPLACEMENT - - -# sorry, have to use module-global variable to capture windows events -var currentEvents: seq[Event] - -template checkWin32Result*(call: untyped) = - let value = call - if value == 0: - raise newException(Exception, "Win32 error: " & astToStr(call) & " returned " & $value) - - -proc MapLeftRightKeys(key: INT, lparam: LPARAM): INT = - case key - of VK_SHIFT: - MapVirtualKey(UINT((lParam and 0x00ff0000) shr 16), MAPVK_VSC_TO_VK_EX) - of VK_CONTROL: - if (lParam and 0x01000000) == 0: VK_LCONTROL else: VK_RCONTROL - of VK_MENU: - if (lParam and 0x01000000) == 0: VK_LMENU else: VK_RMENU - else: - key - -proc WindowHandler(hwnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} = - case uMsg - of WM_DESTROY: - currentEvents.add(Event(eventType: events.EventType.Quit)) - of WM_KEYDOWN, WM_SYSKEYDOWN: - let key = MapLeftRightKeys(INT(wParam), lParam) - currentEvents.add(Event(eventType: KeyPressed, key: KeyTypeMap.getOrDefault(key, Key.UNKNOWN))) - of WM_KEYUP, WM_SYSKEYUP: - let key = MapLeftRightKeys(INT(wParam), lParam) - currentEvents.add(Event(eventType: KeyReleased, key: KeyTypeMap.getOrDefault(key, Key.UNKNOWN))) - of WM_LBUTTONDOWN: - currentEvents.add(Event(eventType: MousePressed, button: MouseButton.Mouse1)) - of WM_LBUTTONUP: - currentEvents.add(Event(eventType: MouseReleased, button: MouseButton.Mouse1)) - of WM_MBUTTONDOWN: - currentEvents.add(Event(eventType: MousePressed, button: MouseButton.Mouse2)) - of WM_MBUTTONUP: - currentEvents.add(Event(eventType: MouseReleased, button: MouseButton.Mouse2)) - of WM_RBUTTONDOWN: - currentEvents.add(Event(eventType: MousePressed, button: MouseButton.Mouse3)) - of WM_RBUTTONUP: - currentEvents.add(Event(eventType: MouseReleased, button: MouseButton.Mouse3)) - of WM_MOUSEMOVE: - currentEvents.add(Event(eventType: events.MouseMoved, x: GET_X_LPARAM(lParam), y: GET_Y_LPARAM(lParam))) - of WM_MOUSEWHEEL: - currentEvents.add(Event(eventType: events.MouseWheel, amount: float32(GET_WHEEL_DELTA_WPARAM(wParam)) / WHEEL_DELTA)) - else: - return DefWindowProc(hwnd, uMsg, wParam, lParam) - - -proc createWindow*(title: string): NativeWindow = - result.hInstance = HINSTANCE(GetModuleHandle(nil)) - var - windowClassName = T"EngineWindowClass" - windowName = T(title) - windowClass = WNDCLASSEX( - cbSize: UINT(WNDCLASSEX.sizeof), - lpfnWndProc: WindowHandler, - hInstance: result.hInstance, - lpszClassName: windowClassName, - hcursor: LoadCursor(HINSTANCE(0), IDC_ARROW), - ) - - if(RegisterClassEx(addr(windowClass)) == 0): - raise newException(Exception, "Unable to register window class") - - result.hwnd = CreateWindowEx( - DWORD(0), - windowClassName, - windowName, - DWORD(WS_OVERLAPPEDWINDOW), - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - HMENU(0), - HINSTANCE(0), - result.hInstance, - nil - ) - - result.g_wpPrev.length = UINT(sizeof(WINDOWPLACEMENT)) - discard ShowWindow(result.hwnd, SW_SHOW) - -# inspired by the one and only, Raymond Chen -# https://devblogs.microsoft.com/oldnewthing/20100412-00/?p=14353 -proc fullscreen*(window: var NativeWindow, enable: bool) = - let dwStyle: DWORD = GetWindowLong(window.hwnd, GWL_STYLE) - if enable: - var mi = MONITORINFO(cbSize: DWORD(sizeof(MONITORINFO))) - if GetWindowPlacement(window.hwnd, addr window.g_wpPrev) and GetMonitorInfo(MonitorFromWindow(window.hwnd, MONITOR_DEFAULTTOPRIMARY), addr mi): - SetWindowLong(window.hwnd, GWL_STYLE, dwStyle and (not WS_OVERLAPPEDWINDOW)) - SetWindowPos(window.hwnd, HWND_TOP, mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top, SWP_NOOWNERZORDER or SWP_FRAMECHANGED) - else: - SetWindowLong(window.hwnd, GWL_STYLE, dwStyle or WS_OVERLAPPEDWINDOW) - SetWindowPlacement(window.hwnd, addr window.g_wpPrev) - SetWindowPos(window.hwnd, HWND(0), 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_NOOWNERZORDER or SWP_FRAMECHANGED) - -proc hideSystemCursor*(window: NativeWindow) = - discard ShowCursor(false) - -proc showSystemCursor*(window: NativeWindow) = - discard ShowCursor(true) - -proc destroy*(window: NativeWindow) = - discard - -proc size*(window: NativeWindow): (int, int) = - var rect: RECT - checkWin32Result GetWindowRect(window.hwnd, addr(rect)) - (int(rect.right - rect.left), int(rect.bottom - rect.top)) - -proc pendingEvents*(window: NativeWindow): seq[Event] = - # empty queue - currentEvents = newSeq[Event]() - var msg: MSG - # fill queue - while PeekMessage(addr(msg), window.hwnd, 0, 0, PM_REMOVE): - TranslateMessage(addr(msg)) - DispatchMessage(addr(msg)) - return currentEvents - -proc getMousePosition*(window: NativeWindow): Option[Vec2f] = - var p: POINT - let res = GetCursorPos(addr(p)) - if res: - return some(Vec2f([float32(p.x), float32(p.y)])) - return none(Vec2f) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/renderer.nim --- a/src/semicongine/renderer.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,508 +0,0 @@ -import std/options -import std/tables -import std/strformat -import std/sequtils -import std/strutils -import std/logging - -import ./core -import ./vulkan/buffer -import ./vulkan/device -import ./vulkan/drawable -import ./vulkan/physicaldevice -import ./vulkan/pipeline -import ./vulkan/renderpass -import ./vulkan/swapchain -import ./vulkan/shader -import ./vulkan/descriptor -import ./vulkan/image - -import ./scene -import ./mesh -import ./material - -const TRANSFORM_ATTRIBUTE = "transform" -const MATERIALINDEX_ATTRIBUTE = "materialIndex" -const VERTEX_ATTRIB_ALIGNMENT = 4 # used for buffer alignment - -type - SceneData = ref object - drawables*: seq[tuple[drawable: Drawable, mesh: Mesh]] - vertexBuffers*: Table[MemoryPerformanceHint, Buffer] - indexBuffer*: Buffer - uniformBuffers*: Table[VkPipeline, seq[Buffer]] # one per frame-in-flight - textures*: Table[VkPipeline, Table[string, seq[VulkanTexture]]] # per frame-in-flight - attributeLocation*: Table[string, MemoryPerformanceHint] - vertexBufferOffsets*: Table[(Mesh, string), int] - descriptorPools*: Table[VkPipeline, DescriptorPool] - descriptorSets*: Table[VkPipeline, seq[DescriptorSet]] - materials: Table[MaterialType, seq[MaterialData]] - Renderer* = object - device: Device - surfaceFormat: VkSurfaceFormatKHR - renderPass: RenderPass - swapchain: Swapchain - scenedata: Table[Scene, SceneData] - emptyTexture: VulkanTexture - -proc initRenderer*(device: Device, shaders: openArray[(MaterialType, ShaderConfiguration)], clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32]), backFaceCulling=true): Renderer = - assert device.vk.valid - - result.device = device - result.renderPass = device.simpleForwardRenderPass(shaders, clearColor=clearColor, backFaceCulling=backFaceCulling) - result.surfaceFormat = device.physicalDevice.getSurfaceFormats().filterSurfaceFormat() - # use last renderpass as output for swapchain - let swapchain = device.createSwapchain(result.renderPass.vk, result.surfaceFormat, device.firstGraphicsQueue().get().family) - if not swapchain.isSome: - raise newException(Exception, "Unable to create swapchain") - - result.swapchain = swapchain.get() - result.emptyTexture = device.uploadTexture(EMPTYTEXTURE) - -func inputs(renderer: Renderer, scene: Scene): seq[ShaderAttribute] = - var found: Table[string, ShaderAttribute] - for i in 0 ..< renderer.renderPass.subpasses.len: - for (materialType, shaderPipeline) in renderer.renderPass.subpasses[i].shaderPipelines: - if scene.usesMaterial(materialType): - for input in shaderPipeline.inputs: - if found.contains(input.name): - assert input.name == found[input.name].name, &"{input.name}: {input.name} != {found[input.name].name}" - assert input.theType == found[input.name].theType, &"{input.name}: {input.theType} != {found[input.name].theType}" - assert input.arrayCount == found[input.name].arrayCount, &"{input.name}: {input.arrayCount} != {found[input.name].arrayCount}" - assert input.memoryPerformanceHint == found[input.name].memoryPerformanceHint, &"{input.name}: {input.memoryPerformanceHint} != {found[input.name].memoryPerformanceHint}" - else: - result.add input - found[input.name] = input - -func materialCompatibleWithPipeline(scene: Scene, materialType: MaterialType, shaderPipeline: ShaderPipeline): (bool, string) = - for uniform in shaderPipeline.uniforms: - if scene.shaderGlobals.contains(uniform.name): - if scene.shaderGlobals[uniform.name].theType != uniform.theType: - return (true, &"shader uniform needs type {uniform.theType} but scene global is of type {scene.shaderGlobals[uniform.name].theType}") - else: - var foundMatch = true - for name, theType in materialType.attributes.pairs: - if name == uniform.name and theType == uniform.theType: - foundMatch = true - break - if not foundMatch: - return (true, &"shader uniform '{uniform.name}' was not found in scene globals or scene materials") - for texture in shaderPipeline.samplers: - if scene.shaderGlobals.contains(texture.name): - if scene.shaderGlobals[texture.name].theType != texture.theType: - return (true, &"shader texture '{texture.name}' needs type {texture.theType} but scene global is of type {scene.shaderGlobals[texture.name].theType}") - else: - var foundMatch = true - for name in materialType.attributes.keys: - if name == texture.name: - foundMatch = true - break - if not foundMatch: - return (true, &"Required texture for shader texture '{texture.name}' was not found in scene materials") - - return (false, "") - -func meshCompatibleWithPipeline(scene: Scene, mesh: Mesh, shaderPipeline: ShaderPipeline): (bool, string) = - for input in shaderPipeline.inputs: - if input.name in [TRANSFORM_ATTRIBUTE, MATERIALINDEX_ATTRIBUTE]: # will be populated automatically - assert input.perInstance == true, &"Currently the {input.name} attribute must be a per instance attribute" - continue - if not (input.name in mesh[].attributes): - return (true, &"Shader input '{input.name}' is not available for mesh") - if input.theType != mesh[].attributeType(input.name): - return (true, &"Shader input '{input.name}' expects type {input.theType}, but mesh has {mesh[].attributeType(input.name)}") - if not input.perInstance and not mesh[].vertexAttributes.contains(input.name): - return (true, &"Shader input '{input.name}' expected to be vertex attribute, but mesh has no such vertex attribute (available are: {mesh[].vertexAttributes})") - if input.perInstance and not mesh[].instanceAttributes.contains(input.name): - return (true, &"Shader input '{input.name}' expected to be per instance attribute, but mesh has no such instance attribute (available are: {mesh[].instanceAttributes})") - - let pipelineCompatability = scene.materialCompatibleWithPipeline(mesh.material.theType, shaderPipeline) - if pipelineCompatability[0]: - return (true, pipelineCompatability[1]) - return (false, "") - -func checkSceneIntegrity(renderer: Renderer, scene: Scene) = - # TODO: this and the sub-functions can likely be simplified a ton - if scene.meshes.len == 0: - return - - var foundRenderableObject = false - var materialTypes: seq[MaterialType] - for i in 0 ..< renderer.renderPass.subpasses.len: - for (materialType, shaderPipeline) in renderer.renderPass.subpasses[i].shaderPipelines: - materialTypes.add materialType - for mesh in scene.meshes: - if mesh.material.theType == materialType: - foundRenderableObject = true - let (error, message) = scene.meshCompatibleWithPipeline(mesh, shaderPipeline) - assert not error, &"Mesh '{mesh}' not compatible with assigned shaderPipeline ({materialType}) because: {message}" - - if not foundRenderableObject: - var matTypes: Table[string, MaterialType] - for mesh in scene.meshes: - if not matTypes.contains(mesh.material.name): - matTypes[mesh.material.name] = mesh.material.theType - assert false, &"Scene '{scene.name}' has been added but materials are not compatible with any registered shader: Materials in scene: {matTypes}, registered shader-materialtypes: {materialTypes}" - -proc setupDrawableBuffers*(renderer: var Renderer, scene: var Scene) = - assert not (scene in renderer.scenedata) - - var scenedata = SceneData() - - # find all material data and group it by material type - for mesh in scene.meshes: - if not scenedata.materials.contains(mesh.material.theType): - scenedata.materials[mesh.material.theType] = @[] - if not scenedata.materials[mesh.material.theType].contains(mesh.material): - scenedata.materials[mesh.material.theType].add mesh.material - - # automatically populate material and tranform attributes - for mesh in scene.meshes: - if not (TRANSFORM_ATTRIBUTE in mesh[].attributes): - mesh[].initInstanceAttribute(TRANSFORM_ATTRIBUTE, Unit4) - if not (MATERIALINDEX_ATTRIBUTE in mesh[].attributes): - mesh[].initInstanceAttribute(MATERIALINDEX_ATTRIBUTE, uint16(scenedata.materials[mesh.material.theType].find(mesh.material))) - - renderer.checkSceneIntegrity(scene) - - let inputs = renderer.inputs(scene) - - # create index buffer if necessary - var indicesBufferSize = 0 - for mesh in scene.meshes: - if mesh[].indexType != MeshIndexType.None: - let indexAlignment = case mesh[].indexType - of MeshIndexType.None: 0 - of Tiny: 1 - of Small: 2 - of Big: 4 - # index value alignment required by Vulkan - if indicesBufferSize mod indexAlignment != 0: - indicesBufferSize += indexAlignment - (indicesBufferSize mod indexAlignment) - indicesBufferSize += mesh[].indexSize - if indicesBufferSize > 0: - scenedata.indexBuffer = renderer.device.createBuffer( - size=indicesBufferSize, - usage=[VK_BUFFER_USAGE_INDEX_BUFFER_BIT], - requireMappable=false, - preferVRAM=true, - ) - - # calculcate offsets for attributes in vertex buffers - # trying to use one buffer per memory type - var perLocationSizes: Table[MemoryPerformanceHint, int] - for hint in MemoryPerformanceHint: - perLocationSizes[hint] = 0 - for attribute in inputs: - scenedata.attributeLocation[attribute.name] = attribute.memoryPerformanceHint - # setup one buffer per attribute-location-type - for mesh in scene.meshes: - # align size to VERTEX_ATTRIB_ALIGNMENT bytes (the important thing is the correct alignment of the offsets, but - # we need to expand the buffer size as well, therefore considering alignment already here as well - if perLocationSizes[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT != 0: - perLocationSizes[attribute.memoryPerformanceHint] += VERTEX_ATTRIB_ALIGNMENT - (perLocationSizes[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT) - perLocationSizes[attribute.memoryPerformanceHint] += mesh[].attributeSize(attribute.name) - - # create vertex buffers - for memoryPerformanceHint, bufferSize in perLocationSizes.pairs: - if bufferSize > 0: - scenedata.vertexBuffers[memoryPerformanceHint] = renderer.device.createBuffer( - size=bufferSize, - usage=[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT], - requireMappable=memoryPerformanceHint==PreferFastWrite, - preferVRAM=true, - ) - - # calculate offset of each attribute for all meshes - var perLocationOffsets: Table[MemoryPerformanceHint, int] - var indexBufferOffset = 0 - for hint in MemoryPerformanceHint: - perLocationOffsets[hint] = 0 - - for mesh in scene.meshes: - for attribute in inputs: - scenedata.vertexBufferOffsets[(mesh, attribute.name)] = perLocationOffsets[attribute.memoryPerformanceHint] - if mesh[].attributes.contains(attribute.name): - let size = mesh[].getRawData(attribute.name)[1] - perLocationOffsets[attribute.memoryPerformanceHint] += size - if perLocationOffsets[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT != 0: - perLocationOffsets[attribute.memoryPerformanceHint] += VERTEX_ATTRIB_ALIGNMENT - (perLocationOffsets[attribute.memoryPerformanceHint] mod VERTEX_ATTRIB_ALIGNMENT) - - # fill offsets per shaderPipeline (as sequence corresponds to shader input binding) - var offsets: Table[VkPipeline, seq[(string, MemoryPerformanceHint, int)]] - for subpass_i in 0 ..< renderer.renderPass.subpasses.len: - for (materialType, shaderPipeline) in renderer.renderPass.subpasses[subpass_i].shaderPipelines: - if scene.usesMaterial(materialType): - offsets[shaderPipeline.vk] = newSeq[(string, MemoryPerformanceHint, int)]() - for attribute in shaderPipeline.inputs: - offsets[shaderPipeline.vk].add (attribute.name, attribute.memoryPerformanceHint, scenedata.vertexBufferOffsets[(mesh, attribute.name)]) - - # create drawables - let indexed = mesh.indexType != MeshIndexType.None - var drawable = Drawable( - name: mesh.name, - elementCount: if indexed: mesh[].indicesCount else: mesh[].vertexCount, - bufferOffsets: offsets, - instanceCount: mesh[].instanceCount, - indexed: indexed, - ) - if indexed: - let indexAlignment = case mesh.indexType - of MeshIndexType.None: 0 - of Tiny: 1 - of Small: 2 - of Big: 4 - # index value alignment required by Vulkan - if indexBufferOffset mod indexAlignment != 0: - indexBufferOffset += indexAlignment - (indexBufferOffset mod indexAlignment) - drawable.indexBufferOffset = indexBufferOffset - drawable.indexType = mesh.indexType - var (pdata, size) = mesh[].getRawIndexData() - scenedata.indexBuffer.setData(pdata, size, indexBufferOffset) - indexBufferOffset += size - scenedata.drawables.add (drawable, mesh) - - # setup uniforms and textures (anything descriptor) - var uploadedTextures: Table[Texture, VulkanTexture] - for subpass_i in 0 ..< renderer.renderPass.subpasses.len: - for (materialType, shaderPipeline) in renderer.renderPass.subpasses[subpass_i].shaderPipelines: - if scene.usesMaterial(materialType): - # gather textures - scenedata.textures[shaderPipeline.vk] = initTable[string, seq[VulkanTexture]]() - for texture in shaderPipeline.samplers: - scenedata.textures[shaderPipeline.vk][texture.name] = newSeq[VulkanTexture]() - if scene.shaderGlobals.contains(texture.name): - for textureValue in getValues[Texture](scene.shaderGlobals[texture.name])[]: - if not uploadedTextures.contains(textureValue): - uploadedTextures[textureValue] = renderer.device.uploadTexture(textureValue) - scenedata.textures[shaderPipeline.vk][texture.name].add uploadedTextures[textureValue] - else: - var foundTexture = false - for material in scene.getMaterials(materialType): - for materialAttribName, value in material.attributes.pairs: - if materialAttribName == texture.name: - if not foundTexture: - foundTexture = true - assert value.theType == TextureType, &"Mesh material has attribute '{materialAttribName}' which is expected to be of type 'Texture' but is of type {value.theType}" - assert value.len == 1, &"Mesh material attribute '{materialAttribName}' has texture-array, but only single textures are allowed" - let textureValue = getValues[Texture](value)[][0] - if not uploadedTextures.contains(textureValue): - uploadedTextures[textureValue] = renderer.device.uploadTexture(textureValue) - scenedata.textures[shaderPipeline.vk][texture.name].add uploadedTextures[textureValue] - break - assert foundTexture, &"No texture found in shaderGlobals or materials for '{texture.name}'" - let nTextures = scenedata.textures[shaderPipeline.vk][texture.name].len - assert (texture.arrayCount == 0 and nTextures == 1) or texture.arrayCount == nTextures, &"Shader assigned to render '{materialType}' expected {texture.arrayCount} textures for '{texture.name}' but got {nTextures}" - - # gather uniform sizes - var uniformBufferSize = 0 - for uniform in shaderPipeline.uniforms: - uniformBufferSize += uniform.size - if uniformBufferSize > 0: - scenedata.uniformBuffers[shaderPipeline.vk] = newSeq[Buffer]() - for frame_i in 0 ..< renderer.swapchain.inFlightFrames: - scenedata.uniformBuffers[shaderPipeline.vk].add renderer.device.createBuffer( - size=uniformBufferSize, - usage=[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT], - requireMappable=true, - preferVRAM=true, - ) - - # setup descriptors - var poolsizes = @[(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, renderer.swapchain.inFlightFrames)] - if scenedata.textures[shaderPipeline.vk].len > 0: - var textureCount = 0 - for textures in scenedata.textures[shaderPipeline.vk].values: - textureCount += textures.len - poolsizes.add (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, renderer.swapchain.inFlightFrames * textureCount * 2) - - scenedata.descriptorPools[shaderPipeline.vk] = renderer.device.createDescriptorSetPool(poolsizes) - - scenedata.descriptorSets[shaderPipeline.vk] = shaderPipeline.setupDescriptors( - scenedata.descriptorPools[shaderPipeline.vk], - scenedata.uniformBuffers.getOrDefault(shaderPipeline.vk, @[]), - scenedata.textures[shaderPipeline.vk], - inFlightFrames=renderer.swapchain.inFlightFrames, - emptyTexture=renderer.emptyTexture, - ) - for frame_i in 0 ..< renderer.swapchain.inFlightFrames: - scenedata.descriptorSets[shaderPipeline.vk][frame_i].writeDescriptorSet() - - renderer.scenedata[scene] = scenedata - -proc refreshMeshAttributeData(renderer: Renderer, scene: var Scene, drawable: Drawable, mesh: Mesh, attribute: string) = - debug &"Refreshing data on mesh mesh for {attribute}" - # ignore attributes that are not used in this shader - if not (attribute in renderer.scenedata[scene].attributeLocation): - return - - let (pdata, size) = mesh[].getRawData(attribute) - let memoryPerformanceHint = renderer.scenedata[scene].attributeLocation[attribute] - renderer.scenedata[scene].vertexBuffers[memoryPerformanceHint].setData(pdata, size, renderer.scenedata[scene].vertexBufferOffsets[(mesh, attribute)]) - -proc updateMeshData*(renderer: var Renderer, scene: var Scene, forceAll=false) = - assert scene in renderer.scenedata - - for (drawable, mesh) in renderer.scenedata[scene].drawables.mitems: - if mesh[].attributes.contains(TRANSFORM_ATTRIBUTE): - mesh[].updateInstanceTransforms(TRANSFORM_ATTRIBUTE) - let attrs = (if forceAll: mesh[].attributes else: mesh[].dirtyAttributes) - for attribute in attrs: - renderer.refreshMeshAttributeData(scene, drawable, mesh, attribute) - debug &"Update mesh attribute {attribute}" - mesh[].clearDirtyAttributes() - -proc updateUniformData*(renderer: var Renderer, scene: var Scene, forceAll=false) = - assert scene in renderer.scenedata - # TODO: maybe check for dirty materials too, but atm we copy materials into the - # renderers scenedata, so they are immutable after initialization, would - # need to allow updates of materials too in order to make sense - - let dirty = scene.dirtyShaderGlobals - if not forceAll and dirty.len == 0: - return - - if forceAll: - debug "Update uniforms because 'forceAll' was given" - else: - debug &"Update uniforms because of dirty scene globals: {dirty}" - - # loop over all used shaders/pipelines - for i in 0 ..< renderer.renderPass.subpasses.len: - for (materialType, shaderPipeline) in renderer.renderPass.subpasses[i].shaderPipelines: - if ( - scene.usesMaterial(materialType) and - renderer.scenedata[scene].uniformBuffers.hasKey(shaderPipeline.vk) and - renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk].len != 0 - ): - assert renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk][renderer.swapchain.currentInFlight].vk.valid - if forceAll: - for buffer in renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk]: - assert buffer.vk.valid - - var offset = 0 - # loop over all uniforms of the shader-shaderPipeline - for uniform in shaderPipeline.uniforms: - if dirty.contains(uniform.name) or forceAll: # only update if necessary - var value: DataList - if scene.shaderGlobals.hasKey(uniform.name): - assert scene.shaderGlobals[uniform.name].thetype == uniform.thetype - value = scene.shaderGlobals[uniform.name] - else: - var foundValue = false - for material in renderer.scenedata[scene].materials[materialType]: - for name, materialValue in material.attributes.pairs: - if uniform.name == name: - if not foundValue: - foundValue = true - value = initDataList(materialValue.theType, 0) - else: - assert value.theType == materialValue.theType, &"Material for uniform '{uniform.name}' was found multiple times with different types: {value.theType} and {materialValue.theType}" - value.appendValues(materialValue) - break - assert foundValue, &"Uniform '{uniform.name}' not found in scene shaderGlobals or materials" - assert (uniform.arrayCount == 0 and value.len == 1) or value.len == uniform.arrayCount, &"Uniform '{uniform.name}' found has wrong length (shader declares {uniform.arrayCount} but shaderGlobals and materials only provide {value.len})" - let (pdata, size) = value.getRawData() - assert size == uniform.size, "During uniform update: gathered value has size {size} but uniform expects size {uniform.size}" - debug &" update uniform {uniform.name} with value: {value}" - # TODO: technically we would only need to update the uniform buffer of the current - # frameInFlight, but we don't track for which frame the shaderglobals are no longer dirty - # therefore we have to update the uniform values in all buffers, of all inFlightframes (usually 2) - for buffer in renderer.scenedata[scene].uniformBuffers[shaderPipeline.vk]: - buffer.setData(pdata, size, offset) - offset += uniform.size - scene.clearDirtyShaderGlobals() - -proc render*(renderer: var Renderer, scene: Scene) = - assert scene in renderer.scenedata - - var - commandBufferResult = renderer.swapchain.nextFrame() - commandBuffer: VkCommandBuffer - - if not commandBufferResult.isSome: - let res = renderer.swapchain.recreate() - if res.isSome: - var oldSwapchain = renderer.swapchain - renderer.swapchain = res.get() - checkVkResult renderer.device.vk.vkDeviceWaitIdle() - oldSwapchain.destroy() - return - - commandBuffer = commandBufferResult.get() - commandBuffer.beginRenderCommands(renderer.renderPass, renderer.swapchain.currentFramebuffer()) - - debug "Scene buffers:" - for (location, buffer) in renderer.scenedata[scene].vertexBuffers.pairs: - debug " ", location, ": ", buffer - debug " Index buffer: ", renderer.scenedata[scene].indexBuffer - - for i in 0 ..< renderer.renderPass.subpasses.len: - for (materialType, shaderPipeline) in renderer.renderPass.subpasses[i].shaderPipelines: - if scene.usesMaterial(materialType): - debug &"Start shaderPipeline for '{materialType}'" - commandBuffer.vkCmdBindPipeline(renderer.renderPass.subpasses[i].pipelineBindPoint, shaderPipeline.vk) - commandBuffer.vkCmdBindDescriptorSets(renderer.renderPass.subpasses[i].pipelineBindPoint, shaderPipeline.layout, 0, 1, addr(renderer.scenedata[scene].descriptorSets[shaderPipeline.vk][renderer.swapchain.currentInFlight].vk), 0, nil) - for (drawable, mesh) in renderer.scenedata[scene].drawables.filterIt(it[1].visible and it[1].material.theType == materialType): - drawable.draw(commandBuffer, vertexBuffers=renderer.scenedata[scene].vertexBuffers, indexBuffer=renderer.scenedata[scene].indexBuffer, shaderPipeline.vk) - - if i < renderer.renderPass.subpasses.len - 1: - commandBuffer.vkCmdNextSubpass(VK_SUBPASS_CONTENTS_INLINE) - - commandBuffer.endRenderCommands() - - if not renderer.swapchain.swap(): - let res = renderer.swapchain.recreate() - if res.isSome: - var oldSwapchain = renderer.swapchain - renderer.swapchain = res.get() - checkVkResult renderer.device.vk.vkDeviceWaitIdle() - oldSwapchain.destroy() - -func framesRendered*(renderer: Renderer): uint64 = - renderer.swapchain.framesRendered - -func valid*(renderer: Renderer): bool = - renderer.device.vk.valid - -proc destroy*(renderer: var Renderer, scene: Scene) = - var scenedata = renderer.scenedata[scene] - - for buffer in scenedata.vertexBuffers.mvalues: - assert buffer.vk.valid - buffer.destroy() - if scenedata.indexBuffer.vk.valid: - assert scenedata.indexBuffer.vk.valid - scenedata.indexBuffer.destroy() - for pipelineUniforms in scenedata.uniformBuffers.mvalues: - for buffer in pipelineUniforms.mitems: - assert buffer.vk.valid - buffer.destroy() - for pipelineTextures in scenedata.textures.mvalues: - for textures in pipelineTextures.mvalues: - for texture in textures.mitems: - texture.destroy() - for descriptorPool in scenedata.descriptorPools.mvalues: - descriptorPool.destroy() - -proc destroy*(renderer: var Renderer) = - for scenedata in renderer.scenedata.mvalues: - for buffer in scenedata.vertexBuffers.mvalues: - assert buffer.vk.valid - buffer.destroy() - if scenedata.indexBuffer.vk.valid: - assert scenedata.indexBuffer.vk.valid - scenedata.indexBuffer.destroy() - for pipelineUniforms in scenedata.uniformBuffers.mvalues: - for buffer in pipelineUniforms.mitems: - assert buffer.vk.valid - buffer.destroy() - for pipelineTextures in scenedata.textures.mvalues: - for textures in pipelineTextures.mvalues: - for texture in textures.mitems: - texture.destroy() - for descriptorPool in scenedata.descriptorPools.mvalues: - descriptorPool.destroy() - renderer.emptyTexture.destroy() - renderer.renderPass.destroy() - renderer.swapchain.destroy() diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/resources.nim --- a/src/semicongine/resources.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -import std/streams -import std/strutils -import std/strformat -import std/os -import std/unicode - -import ./core -import ./resources/image -import ./resources/audio -import ./resources/mesh -import ./resources/font -import ./mesh -import ./material - -export image -export audio -export mesh - -type - ResourceBundlingType = enum - Dir # Directories - Zip # Zip files - Exe # Embeded in executable - -const thebundletype = parseEnum[ResourceBundlingType](BUNDLETYPE.toLowerAscii().capitalizeAscii()) -var selectedMod* = "default" - -# resource loading - -when thebundletype == Dir: - - proc resourceRoot(): string = - joinPath(absolutePath(getAppDir()), RESOURCEROOT) - proc modRoot(): string = - joinPath(resourceRoot(), selectedMod) - - proc loadResource_intern(path: string): Stream = - let realpath = joinPath(modRoot(), path) - if not realpath.fileExists(): - raise newException(Exception, &"Resource {path} not found") - newFileStream(realpath, fmRead) - - proc modList_intern(): seq[string] = - for kind, file in walkDir(resourceRoot(), relative=true): - if kind == pcDir: - result.add file - - iterator walkResources_intern(): string = - for file in walkDirRec(modRoot(), relative=true): - yield file - -elif thebundletype == Zip: - - import zippy/ziparchives - - proc resourceRoot(): string = - joinPath(absolutePath(getAppDir()), RESOURCEROOT) - proc modRoot(): string = - joinPath(resourceRoot(), selectedMod) - - proc loadResource_intern(path: string): Stream = - if not path.fileExists(): - raise newException(Exception, &"Resource {path} not found") - let archive = openZipArchive(modRoot() & ".zip") - # read all here so we can close the stream - result = newStringStream(archive.extractFile(path)) - archive.close() - - proc modList_intern(): seq[string] = - for kind, file in walkDir(resourceRoot(), relative=true): - if kind == pcFile and file.endsWith(".zip"): - result.add file[0 ..< ^4] - - iterator walkResources_intern(): string = - let archive = openZipArchive(modRoot() & ".zip") - for i in archive.walkFiles: - if i[^1] != '/': - yield i - archive.close() - -elif thebundletype == Exe: - - import std/compilesettings - import std/tables - import std/sequtils - - proc loadResources(): Table[string, Table[string, string]] {.compileTime.} = - - let srcdir = joinPath(parentDir(querySetting(projectFull)), RESOURCEROOT) - for kind, moddir in walkDir(srcdir): - if kind == pcDir: - let modname = moddir.splitPath.tail - result[modname] = Table[string, string]() - for resourcefile in walkDirRec(moddir, relative=true): - # TODO: add Lempel–Ziv–Welch compression or something similar simple - result[modname][resourcefile] = staticRead(joinPath(moddir, resourcefile)) - const bundledResources = loadResources() - - proc loadResource_intern(path: string): Stream = - if not (path in bundledResources[selectedMod]): - raise newException(Exception, &"Resource {path} not found") - newStringStream(bundledResources[selectedMod][path]) - - proc modList_intern(): seq[string] = - result = bundledResources.keys().toSeq() - - iterator walkResources_intern(): string = - for i in bundledResources[selectedMod].keys: - yield i - -proc loadResource*(path: string): Stream = - loadResource_intern(path) - -proc loadImage*(path: string): Image = - if path.splitFile().ext.toLowerAscii == ".bmp": - loadResource_intern(path).readBMP() - elif path.splitFile().ext.toLowerAscii == ".png": - loadResource_intern(path).readPNG() - else: - raise newException(Exception, "Unsupported image file type: " & path) - -proc loadAudio*(path: string): Sound = - if path.splitFile().ext.toLowerAscii == ".au": - loadResource_intern(path).readAU() - elif path.splitFile().ext.toLowerAscii == ".ogg": - loadResource_intern(path).readVorbis() - else: - raise newException(Exception, "Unsupported audio file type: " & path) - -proc loadFont*(path: string, name="", color=newVec4f(1, 1, 1, 1), resolution=100'f32): Font = - var thename = name - if thename == "": - thename = path.splitFile().name - let defaultCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_=+[{]};:,<.>/? $!@#%^&*()\"'".toRunes() - loadResource_intern(path).readTrueType(name, defaultCharset, color, resolution) - -proc loadMeshes*(path: string, defaultMaterial: MaterialType): seq[MeshTree] = - loadResource_intern(path).readglTF(defaultMaterial) - -proc loadFirstMesh*(path: string, defaultMaterial: MaterialType): Mesh = - loadResource_intern(path).readglTF(defaultMaterial)[0].toSeq[0] - -proc modList*(): seq[string] = - modList_intern() - -iterator walkResources*(dir=""): string = - for i in walkResources_intern(): - if i.startsWith(dir): - yield i diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/resources/audio.nim --- a/src/semicongine/resources/audio.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -import std/os -import std/streams -import std/strformat -import std/endians - -import ../core/audiotypes - -type - Encoding {.size: sizeof(uint32).} = enum - # Unspecified = 0 - # Uint8Ulaw = 1 - # Int8 = 2 - Int16 = 3 - # Int24 = 4 - # Int32 = 5 - # Float32 = 6 - # Float64 = 7 - - AuHeader = object - magicNumber: uint32 - dataOffset: uint32 - dataSize: uint32 - encoding: Encoding - sampleRate: uint32 - channels: uint32 - -proc readSample(stream: Stream, encoding: Encoding, channels: int): Sample = - result[0] = stream.readint16() - swapEndian16(addr result[0], addr result[0]) - - if channels == 2: - result[1] = stream.readint16() - swapEndian16(addr result[1], addr result[1]) - else: - result[1] = result[0] - -# https://en.wikipedia.org/wiki/Au_file_format -proc readAU*(stream: Stream): Sound = - var header: AuHeader - - for name, value in fieldPairs(header): - var bytes: array[4, uint8] - stream.read(bytes) - swap(bytes[0], bytes[3]) - swap(bytes[1], bytes[2]) - value = cast[typeof(value)](bytes) - - assert header.magicNumber == 0x2e736e64 - if header.sampleRate != AUDIO_SAMPLE_RATE: - raise newException(Exception, &"Only support sample rate of {AUDIO_SAMPLE_RATE} Hz but got {header.sampleRate} Hz, please resample (e.g. ffmpeg -i -ar {AUDIO_SAMPLE_RATE} )") - if not (header.channels in [1'u32, 2'u32]): - raise newException(Exception, "Only support mono and stereo audio at the moment (1 or 2 channels), but found " & $header.channels) - - var annotation: string - stream.read(annotation) - - result = new Sound - stream.setPosition(int(header.dataOffset)) - while not stream.atEnd(): - result[].add stream.readSample(header.encoding, int(header.channels)) - -{.compile: currentSourcePath.parentDir() & "/stb_vorbis.c" .} - -proc stb_vorbis_decode_memory(mem: pointer, len: cint, channels: ptr cint, sample_rate: ptr cint, output: ptr ptr cshort): cint {.importc.} -proc free(p: pointer) {.importc.} - -proc readVorbis*(stream: Stream): Sound = - var - data = stream.readAll() - channels: cint - sampleRate: cint - output: ptr cshort - - var nSamples = stb_vorbis_decode_memory(addr data[0], cint(data.len), addr channels, addr sampleRate, addr output) - - if nSamples < 0: - raise newException(Exception, &"Unable to read ogg/vorbis sound file, error code: {nSamples}") - if sampleRate != AUDIO_SAMPLE_RATE: - raise newException(Exception, &"Only support sample rate of {AUDIO_SAMPLE_RATE} Hz but got {sampleRate} Hz, please resample (e.g. ffmpeg -i -acodec libvorbis -ar {AUDIO_SAMPLE_RATE} )") - - result = new Sound - if channels == 2: - result[].setLen(int(nSamples)) - copyMem(addr result[][0], output, nSamples * sizeof(Sample)) - free(output) - elif channels == 1: - for i in 0 ..< nSamples: - let value = cast[ptr UncheckedArray[int16]](output)[i] - result[].add [value, value] - free(output) - else: - free(output) - raise newException(Exception, "Only support mono and stereo audio at the moment (1 or 2 channels), but found " & $channels) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/resources/font.nim --- a/src/semicongine/resources/font.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -import std/tables -import std/math -import std/streams -import std/os -import std/unicode - -import ../core/vector -import ../core/imagetypes -import ../core/fonttypes - -{.emit: "#define STBTT_STATIC" .} -{.emit: "#define STB_TRUETYPE_IMPLEMENTATION" .} -{.emit: "#include \"" & currentSourcePath.parentDir() & "/stb_truetype.h\"" .} - -type - stbtt_fontinfo {.importc, incompleteStruct .} = object - -proc stbtt_InitFont(info: ptr stbtt_fontinfo, data: ptr char, offset: cint): cint {.importc, nodecl.} -proc stbtt_ScaleForPixelHeight(info: ptr stbtt_fontinfo, pixels: cfloat): cfloat {.importc, nodecl.} -proc stbtt_GetCodepointBitmap(info: ptr stbtt_fontinfo, scale_x: cfloat, scale_y: cfloat, codepoint: cint, width, height, xoff, yoff: ptr cint): cstring {.importc, nodecl.} -proc stbtt_GetCodepointHMetrics(info: ptr stbtt_fontinfo, codepoint: cint, advance, leftBearing: ptr cint) {.importc, nodecl.} -proc stbtt_GetCodepointKernAdvance(info: ptr stbtt_fontinfo, ch1, ch2: cint): cint {.importc, nodecl.} - -proc free(p: pointer) {.importc.} - -proc readTrueType*(stream: Stream, name: string, codePoints: seq[Rune], color: Vec4f, resolution: float32): Font = - var - indata = stream.readAll() - fontinfo: stbtt_fontinfo - if stbtt_InitFont(addr fontinfo, addr indata[0], 0) == 0: - raise newException(Exception, "An error occured while loading PNG file") - - result.resolution = resolution - result.fontscale = float32(stbtt_ScaleForPixelHeight(addr fontinfo, cfloat(resolution))) - var - offsetX = 0 - bitmaps: Table[Rune, (cstring, cint, cint)] - topOffsets: Table[Rune, int] - for codePoint in codePoints: - var - width, height: cint - offX, offY: cint - data = stbtt_GetCodepointBitmap( - addr fontinfo, - result.fontscale, result.fontscale, - cint(codePoint), - addr width, addr height, - addr offX, addr offY - ) - bitmaps[codePoint] = (data, width, height) - result.maxHeight = max(result.maxHeight, int(height)) - offsetX += width + 1 - topOffsets[codePoint] = offY - - result.name = name - result.fontAtlas = Texture( - name: name & "_texture", - image: newImage(offsetX, result.maxHeight + 1), - sampler: FONTSAMPLER_SOFT - ) - - offsetX = 0 - for codePoint in codePoints: - let - bitmap = bitmaps[codePoint][0] - width = bitmaps[codePoint][1] - height = bitmaps[codePoint][2] - - # bitmap data - for y in 0 ..< height: - for x in 0 ..< width: - let value = float32(bitmap[y * width + x]) - result.fontAtlas.image[x + offsetX, y] = [ - uint8(round(color.r * 255'f32)), - uint8(round(color.g * 255'f32)), - uint8(round(color.b * 255'f32)), - uint8(round(color.a * value)) - ] - - # horizontal spaces: - var advance, leftBearing: cint - stbtt_GetCodepointHMetrics(addr fontinfo, cint(codePoint), addr advance, addr leftBearing) - - result.glyphs[codePoint] = GlyphInfo( - dimension: newVec2f(float32(width), float32(height)), - uvs: [ - newVec2f(float32(offsetX) / float32(result.fontAtlas.image.width), int(height) / result.maxHeight), - newVec2f(float32(offsetX) / float32(result.fontAtlas.image.width), 0), - newVec2f(float32(offsetX + width) / float32(result.fontAtlas.image.width), 0), - newVec2f(float32(offsetX + width) / float32(result.fontAtlas.image.width), int(height) / result.maxHeight), - ], - topOffset: float32(topOffsets[codePoint]), - leftOffset: float32(leftBearing) * result.fontscale, - advance: float32(advance) * result.fontscale, - ) - offsetX += width + 1 - free(bitmap) - for codePointAfter in codePoints: - result.kerning[(codePoint, codePointAfter)] = float32(stbtt_GetCodepointKernAdvance( - addr fontinfo, - cint(codePoint), - cint(codePointAfter) - )) * result.fontscale diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/resources/image.nim --- a/src/semicongine/resources/image.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -import os -import std/streams -import std/bitops - -import ../core/imagetypes - -const COMPRESSION_BI_RGB = 0'u32 -const COMPRESSION_BI_BITFIELDS = 3'u32 -const COMPRESSION_BI_ALPHABITFIELDS = 6'u32 -type - BitmapFileHeader = object - magicbytes: array[2, char] - filesize: uint32 - reserved1: uint16 - reserved2: uint16 - dataStart: uint32 - DIBHeader = object - headersize: uint32 - width: int32 - height: int32 - colorPlanes: uint16 - bitsPerPixel: uint16 - compression: uint32 - imageDataSize: uint32 # unused - resolutionX: int32 # unused - resolutionY: int32 # unused - nColors: uint32 # unused - nImportantColors: uint32 # unused - bitMaskRed: uint32 - bitMaskGreen: uint32 - bitMaskBlue: uint32 - bitMaskAlpha: uint32 - colorSpace: array[4, char] # not used yet - colorSpaceEndpoints: array[36, uint8] # unused - gammaRed: uint32 # not used yet - gammaGreen: uint32 # not used yet - gammaBlue: uint32 # not used yet - -proc readBMP*(stream: Stream): Image = - var - bitmapFileHeader: BitmapFileHeader - dibHeader: DIBHeader - - for name, value in fieldPairs(bitmapFileHeader): - stream.read(value) - if bitmapFileHeader.magicbytes != ['B', 'M']: - raise newException(Exception, "Cannot open image, invalid magic bytes (is this really a BMP bitmap?)") - for name, value in fieldPairs(dibHeader): - - when name in ["bitMaskRed", "bitMaskGreen", "bitMaskBlue"]: - if dibHeader.compression in [COMPRESSION_BI_BITFIELDS, COMPRESSION_BI_ALPHABITFIELDS]: - stream.read(value) - elif name == "bitMaskAlpha": - if dibHeader.compression == COMPRESSION_BI_ALPHABITFIELDS: - stream.read(value) - else: - stream.read(value) - - when name == "headersize": - if value != 124: - raise newException(Exception, "Cannot open image, only BITMAPV5 supported") - elif name == "colorPlanes": - assert value == 1 - elif name == "bitsPerPixel": - if not (value in [24'u16, 32'u16]): - raise newException(Exception, "Cannot open image, only depth of 24 and 32 supported") - elif name == "compression": - if not (value in [0'u32, 3'u32]): - raise newException(Exception, "Cannot open image, only BI_RGB and BI_BITFIELDS are supported compressions") - elif name == "colorSpace": - swap(value[0], value[3]) - swap(value[1], value[2]) - stream.setPosition(int(bitmapFileHeader.dataStart)) - var - padding = ((int32(dibHeader.bitsPerPixel div 8)) * dibHeader.width) mod 4 - data = newSeq[Pixel](dibHeader.width * abs(dibHeader.height)) - if padding > 0: - padding = 4 - padding - for row in 0 ..< abs(dibHeader.height): - for col in 0 ..< dibHeader.width: - - var pixel: Pixel = [0'u8, 0'u8, 0'u8, 255'u8] - # if we got channeld bitmasks - if dibHeader.compression in [COMPRESSION_BI_BITFIELDS, COMPRESSION_BI_ALPHABITFIELDS]: - var value = stream.readUint32() - pixel[0] = uint8((value and dibHeader.bitMaskRed) shr dibHeader.bitMaskRed.countTrailingZeroBits) - pixel[1] = uint8((value and dibHeader.bitMaskGreen) shr dibHeader.bitMaskGreen.countTrailingZeroBits) - pixel[2] = uint8((value and dibHeader.bitMaskBlue) shr dibHeader.bitMaskBlue.countTrailingZeroBits) - if dibHeader.compression == COMPRESSION_BI_ALPHABITFIELDS: - pixel[3] = uint8((value and dibHeader.bitMaskAlpha) shr dibHeader.bitMaskAlpha.countTrailingZeroBits) - # if we got plain RGB(A), using little endian - elif dibHeader.compression == COMPRESSION_BI_RGB: - let nChannels = int(dibHeader.bitsPerPixel) div 8 - for i in 1 .. nChannels: - stream.read(pixel[nChannels - i]) - else: - raise newException(Exception, "Cannot open image, only BI_RGB and BI_BITFIELDS are supported compressions") - - # determine whether we read top-to-bottom or bottom-to-top - var row_mult: int = (if dibHeader.height < 0: row else: dibHeader.height - row - 1) - data[row_mult * dibHeader.width + col]= pixel - stream.setPosition(stream.getPosition() + padding) - - result = newImage(width=dibHeader.width, height=abs(dibHeader.height), imagedata=data) - -{.compile: currentSourcePath.parentDir() & "/lodepng.c" .} - -proc lodepng_decode32(out_data: ptr cstring, w: ptr cuint, h: ptr cuint, in_data: cstring, insize: csize_t): cuint {.importc.} -proc free(p: pointer) {.importc.} # for some reason the lodepng pointer can only properly be freed with the native free - -proc readPNG*(stream: Stream): Image = - let indata = stream.readAll() - var w, h: cuint - var data: cstring - - if lodepng_decode32(out_data=addr data, w=addr w, h=addr h, in_data=cstring(indata), insize=csize_t(indata.len)) != 0: - raise newException(Exception, "An error occured while loading PNG file") - - let imagesize = w * h * 4 - var imagedata = newSeq[Pixel](w * h) - copyMem(addr imagedata[0], data, imagesize) - - free(data) - - result = newImage(width=int(w), height=int(h), imagedata=imagedata) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/resources/lodepng.c --- a/src/semicongine/resources/lodepng.c Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6991 +0,0 @@ -/* -LodePNG version 20230410 - -Copyright (c) 2005-2023 Lode Vandevenne - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*/ - -/* -The manual and changelog are in the header file "lodepng.h" -Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C. -*/ - -#include "lodepng.h" - -#ifdef LODEPNG_COMPILE_DISK -#include /* LONG_MAX */ -#include /* file handling */ -#endif /* LODEPNG_COMPILE_DISK */ - -#ifdef LODEPNG_COMPILE_ALLOCATORS -#include /* allocations */ -#endif /* LODEPNG_COMPILE_ALLOCATORS */ - -#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/ -#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/ -#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ -#endif /*_MSC_VER */ - -const char* LODEPNG_VERSION_STRING = "20230410"; - -/* -This source file is divided into the following large parts. The code sections -with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way. --Tools for C and common code for PNG and Zlib --C Code for Zlib (huffman, deflate, ...) --C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...) --The C++ wrapper around all of the above -*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // Tools for C, and common code for PNG and Zlib. // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*The malloc, realloc and free functions defined here with "lodepng_" in front -of the name, so that you can easily change them to others related to your -platform if needed. Everything else in the code calls these. Pass --DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out -#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and -define them in your own project's source files without needing to change -lodepng source code. Don't forget to remove "static" if you copypaste them -from here.*/ - -#ifdef LODEPNG_COMPILE_ALLOCATORS -static void* lodepng_malloc(size_t size) { -#ifdef LODEPNG_MAX_ALLOC - if(size > LODEPNG_MAX_ALLOC) return 0; -#endif - return malloc(size); -} - -/* NOTE: when realloc returns NULL, it leaves the original memory untouched */ -static void* lodepng_realloc(void* ptr, size_t new_size) { -#ifdef LODEPNG_MAX_ALLOC - if(new_size > LODEPNG_MAX_ALLOC) return 0; -#endif - return realloc(ptr, new_size); -} - -static void lodepng_free(void* ptr) { - free(ptr); -} -#else /*LODEPNG_COMPILE_ALLOCATORS*/ -/* TODO: support giving additional void* payload to the custom allocators */ -void* lodepng_malloc(size_t size); -void* lodepng_realloc(void* ptr, size_t new_size); -void lodepng_free(void* ptr); -#endif /*LODEPNG_COMPILE_ALLOCATORS*/ - -/* convince the compiler to inline a function, for use when this measurably improves performance */ -/* inline is not available in C90, but use it when supported by the compiler */ -#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined(__cplusplus) && (__cplusplus >= 199711L)) -#define LODEPNG_INLINE inline -#else -#define LODEPNG_INLINE /* not available */ -#endif - -/* restrict is not available in C90, but use it when supported by the compiler */ -#if (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) ||\ - (defined(_MSC_VER) && (_MSC_VER >= 1400)) || \ - (defined(__WATCOMC__) && (__WATCOMC__ >= 1250) && !defined(__cplusplus)) -#define LODEPNG_RESTRICT __restrict -#else -#define LODEPNG_RESTRICT /* not available */ -#endif - -/* Replacements for C library functions such as memcpy and strlen, to support platforms -where a full C library is not available. The compiler can recognize them and compile -to something as fast. */ - -static void lodepng_memcpy(void* LODEPNG_RESTRICT dst, - const void* LODEPNG_RESTRICT src, size_t size) { - size_t i; - for(i = 0; i < size; i++) ((char*)dst)[i] = ((const char*)src)[i]; -} - -static void lodepng_memset(void* LODEPNG_RESTRICT dst, - int value, size_t num) { - size_t i; - for(i = 0; i < num; i++) ((char*)dst)[i] = (char)value; -} - -/* does not check memory out of bounds, do not use on untrusted data */ -static size_t lodepng_strlen(const char* a) { - const char* orig = a; - /* avoid warning about unused function in case of disabled COMPILE... macros */ - (void)(&lodepng_strlen); - while(*a) a++; - return (size_t)(a - orig); -} - -#define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b)) - -#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER) -/* Safely check if adding two integers will overflow (no undefined -behavior, compiler removing the code, etc...) and output result. */ -static int lodepng_addofl(size_t a, size_t b, size_t* result) { - *result = a + b; /* Unsigned addition is well defined and safe in C90 */ - return *result < a; -} -#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)*/ - -#ifdef LODEPNG_COMPILE_DECODER -/* Safely check if multiplying two integers will overflow (no undefined -behavior, compiler removing the code, etc...) and output result. */ -static int lodepng_mulofl(size_t a, size_t b, size_t* result) { - *result = a * b; /* Unsigned multiplication is well defined and safe in C90 */ - return (a != 0 && *result / a != b); -} - -#ifdef LODEPNG_COMPILE_ZLIB -/* Safely check if a + b > c, even if overflow could happen. */ -static int lodepng_gtofl(size_t a, size_t b, size_t c) { - size_t d; - if(lodepng_addofl(a, b, &d)) return 1; - return d > c; -} -#endif /*LODEPNG_COMPILE_ZLIB*/ -#endif /*LODEPNG_COMPILE_DECODER*/ - - -/* -Often in case of an error a value is assigned to a variable and then it breaks -out of a loop (to go to the cleanup phase of a function). This macro does that. -It makes the error handling code shorter and more readable. - -Example: if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83); -*/ -#define CERROR_BREAK(errorvar, code){\ - errorvar = code;\ - break;\ -} - -/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/ -#define ERROR_BREAK(code) CERROR_BREAK(error, code) - -/*Set error var to the error code, and return it.*/ -#define CERROR_RETURN_ERROR(errorvar, code){\ - errorvar = code;\ - return code;\ -} - -/*Try the code, if it returns error, also return the error.*/ -#define CERROR_TRY_RETURN(call){\ - unsigned error = call;\ - if(error) return error;\ -} - -/*Set error var to the error code, and return from the void function.*/ -#define CERROR_RETURN(errorvar, code){\ - errorvar = code;\ - return;\ -} - -/* -About uivector, ucvector and string: --All of them wrap dynamic arrays or text strings in a similar way. --LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. --The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. --They're not used in the interface, only internally in this file as static functions. --As with many other structs in this file, the init and cleanup functions serve as ctor and dtor. -*/ - -#ifdef LODEPNG_COMPILE_ZLIB -#ifdef LODEPNG_COMPILE_ENCODER -/*dynamic vector of unsigned ints*/ -typedef struct uivector { - unsigned* data; - size_t size; /*size in number of unsigned longs*/ - size_t allocsize; /*allocated size in bytes*/ -} uivector; - -static void uivector_cleanup(void* p) { - ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; - lodepng_free(((uivector*)p)->data); - ((uivector*)p)->data = NULL; -} - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned uivector_resize(uivector* p, size_t size) { - size_t allocsize = size * sizeof(unsigned); - if(allocsize > p->allocsize) { - size_t newsize = allocsize + (p->allocsize >> 1u); - void* data = lodepng_realloc(p->data, newsize); - if(data) { - p->allocsize = newsize; - p->data = (unsigned*)data; - } - else return 0; /*error: not enough memory*/ - } - p->size = size; - return 1; /*success*/ -} - -static void uivector_init(uivector* p) { - p->data = NULL; - p->size = p->allocsize = 0; -} - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned uivector_push_back(uivector* p, unsigned c) { - if(!uivector_resize(p, p->size + 1)) return 0; - p->data[p->size - 1] = c; - return 1; -} -#endif /*LODEPNG_COMPILE_ENCODER*/ -#endif /*LODEPNG_COMPILE_ZLIB*/ - -/* /////////////////////////////////////////////////////////////////////////// */ - -/*dynamic vector of unsigned chars*/ -typedef struct ucvector { - unsigned char* data; - size_t size; /*used size*/ - size_t allocsize; /*allocated size*/ -} ucvector; - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned ucvector_reserve(ucvector* p, size_t size) { - if(size > p->allocsize) { - size_t newsize = size + (p->allocsize >> 1u); - void* data = lodepng_realloc(p->data, newsize); - if(data) { - p->allocsize = newsize; - p->data = (unsigned char*)data; - } - else return 0; /*error: not enough memory*/ - } - return 1; /*success*/ -} - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned ucvector_resize(ucvector* p, size_t size) { - p->size = size; - return ucvector_reserve(p, size); -} - -static ucvector ucvector_init(unsigned char* buffer, size_t size) { - ucvector v; - v.data = buffer; - v.allocsize = v.size = size; - return v; -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_PNG -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - -/*free string pointer and set it to NULL*/ -static void string_cleanup(char** out) { - lodepng_free(*out); - *out = NULL; -} - -/*also appends null termination character*/ -static char* alloc_string_sized(const char* in, size_t insize) { - char* out = (char*)lodepng_malloc(insize + 1); - if(out) { - lodepng_memcpy(out, in, insize); - out[insize] = 0; - } - return out; -} - -/* dynamically allocates a new string with a copy of the null terminated input text */ -static char* alloc_string(const char* in) { - return alloc_string_sized(in, lodepng_strlen(in)); -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -/* ////////////////////////////////////////////////////////////////////////// */ - -#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG) -static unsigned lodepng_read32bitInt(const unsigned char* buffer) { - return (((unsigned)buffer[0] << 24u) | ((unsigned)buffer[1] << 16u) | - ((unsigned)buffer[2] << 8u) | (unsigned)buffer[3]); -} -#endif /*defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG)*/ - -#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) -/*buffer must have at least 4 allocated bytes available*/ -static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) { - buffer[0] = (unsigned char)((value >> 24) & 0xff); - buffer[1] = (unsigned char)((value >> 16) & 0xff); - buffer[2] = (unsigned char)((value >> 8) & 0xff); - buffer[3] = (unsigned char)((value ) & 0xff); -} -#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / File IO / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_DISK - -/* returns negative value on error. This should be pure C compatible, so no fstat. */ -static long lodepng_filesize(const char* filename) { - FILE* file; - long size; - file = fopen(filename, "rb"); - if(!file) return -1; - - if(fseek(file, 0, SEEK_END) != 0) { - fclose(file); - return -1; - } - - size = ftell(file); - /* It may give LONG_MAX as directory size, this is invalid for us. */ - if(size == LONG_MAX) size = -1; - - fclose(file); - return size; -} - -/* load file into buffer that already has the correct allocated size. Returns error code.*/ -static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) { - FILE* file; - size_t readsize; - file = fopen(filename, "rb"); - if(!file) return 78; - - readsize = fread(out, 1, size, file); - fclose(file); - - if(readsize != size) return 78; - return 0; -} - -unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) { - long size = lodepng_filesize(filename); - if(size < 0) return 78; - *outsize = (size_t)size; - - *out = (unsigned char*)lodepng_malloc((size_t)size); - if(!(*out) && size > 0) return 83; /*the above malloc failed*/ - - return lodepng_buffer_file(*out, (size_t)size, filename); -} - -/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ -unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) { - FILE* file; - file = fopen(filename, "wb" ); - if(!file) return 79; - fwrite(buffer, 1, buffersize, file); - fclose(file); - return 0; -} - -#endif /*LODEPNG_COMPILE_DISK*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // End of common code and tools. Begin of Zlib related code. // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_ZLIB -#ifdef LODEPNG_COMPILE_ENCODER - -typedef struct { - ucvector* data; - unsigned char bp; /*ok to overflow, indicates bit pos inside byte*/ -} LodePNGBitWriter; - -static void LodePNGBitWriter_init(LodePNGBitWriter* writer, ucvector* data) { - writer->data = data; - writer->bp = 0; -} - -/*TODO: this ignores potential out of memory errors*/ -#define WRITEBIT(writer, bit){\ - /* append new byte */\ - if(((writer->bp) & 7u) == 0) {\ - if(!ucvector_resize(writer->data, writer->data->size + 1)) return;\ - writer->data->data[writer->data->size - 1] = 0;\ - }\ - (writer->data->data[writer->data->size - 1]) |= (bit << ((writer->bp) & 7u));\ - ++writer->bp;\ -} - -/* LSB of value is written first, and LSB of bytes is used first */ -static void writeBits(LodePNGBitWriter* writer, unsigned value, size_t nbits) { - if(nbits == 1) { /* compiler should statically compile this case if nbits == 1 */ - WRITEBIT(writer, value); - } else { - /* TODO: increase output size only once here rather than in each WRITEBIT */ - size_t i; - for(i = 0; i != nbits; ++i) { - WRITEBIT(writer, (unsigned char)((value >> i) & 1)); - } - } -} - -/* This one is to use for adding huffman symbol, the value bits are written MSB first */ -static void writeBitsReversed(LodePNGBitWriter* writer, unsigned value, size_t nbits) { - size_t i; - for(i = 0; i != nbits; ++i) { - /* TODO: increase output size only once here rather than in each WRITEBIT */ - WRITEBIT(writer, (unsigned char)((value >> (nbits - 1u - i)) & 1u)); - } -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#ifdef LODEPNG_COMPILE_DECODER - -typedef struct { - const unsigned char* data; - size_t size; /*size of data in bytes*/ - size_t bitsize; /*size of data in bits, end of valid bp values, should be 8*size*/ - size_t bp; - unsigned buffer; /*buffer for reading bits. NOTE: 'unsigned' must support at least 32 bits*/ -} LodePNGBitReader; - -/* data size argument is in bytes. Returns error if size too large causing overflow */ -static unsigned LodePNGBitReader_init(LodePNGBitReader* reader, const unsigned char* data, size_t size) { - size_t temp; - reader->data = data; - reader->size = size; - /* size in bits, return error if overflow (if size_t is 32 bit this supports up to 500MB) */ - if(lodepng_mulofl(size, 8u, &reader->bitsize)) return 105; - /*ensure incremented bp can be compared to bitsize without overflow even when it would be incremented 32 too much and - trying to ensure 32 more bits*/ - if(lodepng_addofl(reader->bitsize, 64u, &temp)) return 105; - reader->bp = 0; - reader->buffer = 0; - return 0; /*ok*/ -} - -/* -ensureBits functions: -Ensures the reader can at least read nbits bits in one or more readBits calls, -safely even if not enough bits are available. -The nbits parameter is unused but is given for documentation purposes, error -checking for amount of bits must be done beforehand. -*/ - -/*See ensureBits documentation above. This one ensures up to 9 bits */ -static LODEPNG_INLINE void ensureBits9(LodePNGBitReader* reader, size_t nbits) { - size_t start = reader->bp >> 3u; - size_t size = reader->size; - if(start + 1u < size) { - reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u); - reader->buffer >>= (reader->bp & 7u); - } else { - reader->buffer = 0; - if(start + 0u < size) reader->buffer = reader->data[start + 0]; - reader->buffer >>= (reader->bp & 7u); - } - (void)nbits; -} - -/*See ensureBits documentation above. This one ensures up to 17 bits */ -static LODEPNG_INLINE void ensureBits17(LodePNGBitReader* reader, size_t nbits) { - size_t start = reader->bp >> 3u; - size_t size = reader->size; - if(start + 2u < size) { - reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | - ((unsigned)reader->data[start + 2] << 16u); - reader->buffer >>= (reader->bp & 7u); - } else { - reader->buffer = 0; - if(start + 0u < size) reader->buffer |= reader->data[start + 0]; - if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); - reader->buffer >>= (reader->bp & 7u); - } - (void)nbits; -} - -/*See ensureBits documentation above. This one ensures up to 25 bits */ -static LODEPNG_INLINE void ensureBits25(LodePNGBitReader* reader, size_t nbits) { - size_t start = reader->bp >> 3u; - size_t size = reader->size; - if(start + 3u < size) { - reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | - ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u); - reader->buffer >>= (reader->bp & 7u); - } else { - reader->buffer = 0; - if(start + 0u < size) reader->buffer |= reader->data[start + 0]; - if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); - if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u); - reader->buffer >>= (reader->bp & 7u); - } - (void)nbits; -} - -/*See ensureBits documentation above. This one ensures up to 32 bits */ -static LODEPNG_INLINE void ensureBits32(LodePNGBitReader* reader, size_t nbits) { - size_t start = reader->bp >> 3u; - size_t size = reader->size; - if(start + 4u < size) { - reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | - ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u); - reader->buffer >>= (reader->bp & 7u); - reader->buffer |= (((unsigned)reader->data[start + 4] << 24u) << (8u - (reader->bp & 7u))); - } else { - reader->buffer = 0; - if(start + 0u < size) reader->buffer |= reader->data[start + 0]; - if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); - if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u); - if(start + 3u < size) reader->buffer |= ((unsigned)reader->data[start + 3] << 24u); - reader->buffer >>= (reader->bp & 7u); - } - (void)nbits; -} - -/* Get bits without advancing the bit pointer. Must have enough bits available with ensureBits. Max nbits is 31. */ -static LODEPNG_INLINE unsigned peekBits(LodePNGBitReader* reader, size_t nbits) { - /* The shift allows nbits to be only up to 31. */ - return reader->buffer & ((1u << nbits) - 1u); -} - -/* Must have enough bits available with ensureBits */ -static LODEPNG_INLINE void advanceBits(LodePNGBitReader* reader, size_t nbits) { - reader->buffer >>= nbits; - reader->bp += nbits; -} - -/* Must have enough bits available with ensureBits */ -static LODEPNG_INLINE unsigned readBits(LodePNGBitReader* reader, size_t nbits) { - unsigned result = peekBits(reader, nbits); - advanceBits(reader, nbits); - return result; -} -#endif /*LODEPNG_COMPILE_DECODER*/ - -static unsigned reverseBits(unsigned bits, unsigned num) { - /*TODO: implement faster lookup table based version when needed*/ - unsigned i, result = 0; - for(i = 0; i < num; i++) result |= ((bits >> (num - i - 1u)) & 1u) << i; - return result; -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Deflate - Huffman / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#define FIRST_LENGTH_CODE_INDEX 257 -#define LAST_LENGTH_CODE_INDEX 285 -/*256 literals, the end code, some length codes, and 2 unused codes*/ -#define NUM_DEFLATE_CODE_SYMBOLS 288 -/*the distance codes have their own symbols, 30 used, 2 unused*/ -#define NUM_DISTANCE_SYMBOLS 32 -/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ -#define NUM_CODE_LENGTH_CODES 19 - -/*the base lengths represented by codes 257-285*/ -static const unsigned LENGTHBASE[29] - = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, - 67, 83, 99, 115, 131, 163, 195, 227, 258}; - -/*the extra bits used by codes 257-285 (added to base length)*/ -static const unsigned LENGTHEXTRA[29] - = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, - 4, 4, 4, 4, 5, 5, 5, 5, 0}; - -/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ -static const unsigned DISTANCEBASE[30] - = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, - 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; - -/*the extra bits of backwards distances (added to base)*/ -static const unsigned DISTANCEEXTRA[30] - = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; - -/*the order in which "code length alphabet code lengths" are stored as specified by deflate, out of this the huffman -tree of the dynamic huffman tree lengths is generated*/ -static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES] - = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* ////////////////////////////////////////////////////////////////////////// */ - -/* -Huffman tree struct, containing multiple representations of the tree -*/ -typedef struct HuffmanTree { - unsigned* codes; /*the huffman codes (bit patterns representing the symbols)*/ - unsigned* lengths; /*the lengths of the huffman codes*/ - unsigned maxbitlen; /*maximum number of bits a single code can get*/ - unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ - /* for reading only */ - unsigned char* table_len; /*length of symbol from lookup table, or max length if secondary lookup needed*/ - unsigned short* table_value; /*value of symbol from lookup table, or pointer to secondary table if needed*/ -} HuffmanTree; - -static void HuffmanTree_init(HuffmanTree* tree) { - tree->codes = 0; - tree->lengths = 0; - tree->table_len = 0; - tree->table_value = 0; -} - -static void HuffmanTree_cleanup(HuffmanTree* tree) { - lodepng_free(tree->codes); - lodepng_free(tree->lengths); - lodepng_free(tree->table_len); - lodepng_free(tree->table_value); -} - -/* amount of bits for first huffman table lookup (aka root bits), see HuffmanTree_makeTable and huffmanDecodeSymbol.*/ -/* values 8u and 9u work the fastest */ -#define FIRSTBITS 9u - -/* a symbol value too big to represent any valid symbol, to indicate reading disallowed huffman bits combination, -which is possible in case of only 0 or 1 present symbols. */ -#define INVALIDSYMBOL 65535u - -/* make table for huffman decoding */ -static unsigned HuffmanTree_makeTable(HuffmanTree* tree) { - static const unsigned headsize = 1u << FIRSTBITS; /*size of the first table*/ - static const unsigned mask = (1u << FIRSTBITS) /*headsize*/ - 1u; - size_t i, numpresent, pointer, size; /*total table size*/ - unsigned* maxlens = (unsigned*)lodepng_malloc(headsize * sizeof(unsigned)); - if(!maxlens) return 83; /*alloc fail*/ - - /* compute maxlens: max total bit length of symbols sharing prefix in the first table*/ - lodepng_memset(maxlens, 0, headsize * sizeof(*maxlens)); - for(i = 0; i < tree->numcodes; i++) { - unsigned symbol = tree->codes[i]; - unsigned l = tree->lengths[i]; - unsigned index; - if(l <= FIRSTBITS) continue; /*symbols that fit in first table don't increase secondary table size*/ - /*get the FIRSTBITS MSBs, the MSBs of the symbol are encoded first. See later comment about the reversing*/ - index = reverseBits(symbol >> (l - FIRSTBITS), FIRSTBITS); - maxlens[index] = LODEPNG_MAX(maxlens[index], l); - } - /* compute total table size: size of first table plus all secondary tables for symbols longer than FIRSTBITS */ - size = headsize; - for(i = 0; i < headsize; ++i) { - unsigned l = maxlens[i]; - if(l > FIRSTBITS) size += (1u << (l - FIRSTBITS)); - } - tree->table_len = (unsigned char*)lodepng_malloc(size * sizeof(*tree->table_len)); - tree->table_value = (unsigned short*)lodepng_malloc(size * sizeof(*tree->table_value)); - if(!tree->table_len || !tree->table_value) { - lodepng_free(maxlens); - /* freeing tree->table values is done at a higher scope */ - return 83; /*alloc fail*/ - } - /*initialize with an invalid length to indicate unused entries*/ - for(i = 0; i < size; ++i) tree->table_len[i] = 16; - - /*fill in the first table for long symbols: max prefix size and pointer to secondary tables*/ - pointer = headsize; - for(i = 0; i < headsize; ++i) { - unsigned l = maxlens[i]; - if(l <= FIRSTBITS) continue; - tree->table_len[i] = l; - tree->table_value[i] = pointer; - pointer += (1u << (l - FIRSTBITS)); - } - lodepng_free(maxlens); - - /*fill in the first table for short symbols, or secondary table for long symbols*/ - numpresent = 0; - for(i = 0; i < tree->numcodes; ++i) { - unsigned l = tree->lengths[i]; - unsigned symbol, reverse; - if(l == 0) continue; - symbol = tree->codes[i]; /*the huffman bit pattern. i itself is the value.*/ - /*reverse bits, because the huffman bits are given in MSB first order but the bit reader reads LSB first*/ - reverse = reverseBits(symbol, l); - numpresent++; - - if(l <= FIRSTBITS) { - /*short symbol, fully in first table, replicated num times if l < FIRSTBITS*/ - unsigned num = 1u << (FIRSTBITS - l); - unsigned j; - for(j = 0; j < num; ++j) { - /*bit reader will read the l bits of symbol first, the remaining FIRSTBITS - l bits go to the MSB's*/ - unsigned index = reverse | (j << l); - if(tree->table_len[index] != 16) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ - tree->table_len[index] = l; - tree->table_value[index] = i; - } - } else { - /*long symbol, shares prefix with other long symbols in first lookup table, needs second lookup*/ - /*the FIRSTBITS MSBs of the symbol are the first table index*/ - unsigned index = reverse & mask; - unsigned maxlen = tree->table_len[index]; - /*log2 of secondary table length, should be >= l - FIRSTBITS*/ - unsigned tablelen = maxlen - FIRSTBITS; - unsigned start = tree->table_value[index]; /*starting index in secondary table*/ - unsigned num = 1u << (tablelen - (l - FIRSTBITS)); /*amount of entries of this symbol in secondary table*/ - unsigned j; - if(maxlen < l) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ - for(j = 0; j < num; ++j) { - unsigned reverse2 = reverse >> FIRSTBITS; /* l - FIRSTBITS bits */ - unsigned index2 = start + (reverse2 | (j << (l - FIRSTBITS))); - tree->table_len[index2] = l; - tree->table_value[index2] = i; - } - } - } - - if(numpresent < 2) { - /* In case of exactly 1 symbol, in theory the huffman symbol needs 0 bits, - but deflate uses 1 bit instead. In case of 0 symbols, no symbols can - appear at all, but such huffman tree could still exist (e.g. if distance - codes are never used). In both cases, not all symbols of the table will be - filled in. Fill them in with an invalid symbol value so returning them from - huffmanDecodeSymbol will cause error. */ - for(i = 0; i < size; ++i) { - if(tree->table_len[i] == 16) { - /* As length, use a value smaller than FIRSTBITS for the head table, - and a value larger than FIRSTBITS for the secondary table, to ensure - valid behavior for advanceBits when reading this symbol. */ - tree->table_len[i] = (i < headsize) ? 1 : (FIRSTBITS + 1); - tree->table_value[i] = INVALIDSYMBOL; - } - } - } else { - /* A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. - If that is not the case (due to too long length codes), the table will not - have been fully used, and this is an error (not all bit combinations can be - decoded): an oversubscribed huffman tree, indicated by error 55. */ - for(i = 0; i < size; ++i) { - if(tree->table_len[i] == 16) return 55; - } - } - - return 0; -} - -/* -Second step for the ...makeFromLengths and ...makeFromFrequencies functions. -numcodes, lengths and maxbitlen must already be filled in correctly. return -value is error. -*/ -static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) { - unsigned* blcount; - unsigned* nextcode; - unsigned error = 0; - unsigned bits, n; - - tree->codes = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned)); - blcount = (unsigned*)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned)); - nextcode = (unsigned*)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned)); - if(!tree->codes || !blcount || !nextcode) error = 83; /*alloc fail*/ - - if(!error) { - for(n = 0; n != tree->maxbitlen + 1; n++) blcount[n] = nextcode[n] = 0; - /*step 1: count number of instances of each code length*/ - for(bits = 0; bits != tree->numcodes; ++bits) ++blcount[tree->lengths[bits]]; - /*step 2: generate the nextcode values*/ - for(bits = 1; bits <= tree->maxbitlen; ++bits) { - nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1u; - } - /*step 3: generate all the codes*/ - for(n = 0; n != tree->numcodes; ++n) { - if(tree->lengths[n] != 0) { - tree->codes[n] = nextcode[tree->lengths[n]]++; - /*remove superfluous bits from the code*/ - tree->codes[n] &= ((1u << tree->lengths[n]) - 1u); - } - } - } - - lodepng_free(blcount); - lodepng_free(nextcode); - - if(!error) error = HuffmanTree_makeTable(tree); - return error; -} - -/* -given the code lengths (as stored in the PNG file), generate the tree as defined -by Deflate. maxbitlen is the maximum bits that a code in the tree can have. -return value is error. -*/ -static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, - size_t numcodes, unsigned maxbitlen) { - unsigned i; - tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); - if(!tree->lengths) return 83; /*alloc fail*/ - for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i]; - tree->numcodes = (unsigned)numcodes; /*number of symbols*/ - tree->maxbitlen = maxbitlen; - return HuffmanTree_makeFromLengths2(tree); -} - -#ifdef LODEPNG_COMPILE_ENCODER - -/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding", -Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/ - -/*chain node for boundary package merge*/ -typedef struct BPMNode { - int weight; /*the sum of all weights in this chain*/ - unsigned index; /*index of this leaf node (called "count" in the paper)*/ - struct BPMNode* tail; /*the next nodes in this chain (null if last)*/ - int in_use; -} BPMNode; - -/*lists of chains*/ -typedef struct BPMLists { - /*memory pool*/ - unsigned memsize; - BPMNode* memory; - unsigned numfree; - unsigned nextfree; - BPMNode** freelist; - /*two heads of lookahead chains per list*/ - unsigned listsize; - BPMNode** chains0; - BPMNode** chains1; -} BPMLists; - -/*creates a new chain node with the given parameters, from the memory in the lists */ -static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) { - unsigned i; - BPMNode* result; - - /*memory full, so garbage collect*/ - if(lists->nextfree >= lists->numfree) { - /*mark only those that are in use*/ - for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0; - for(i = 0; i != lists->listsize; ++i) { - BPMNode* node; - for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1; - for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1; - } - /*collect those that are free*/ - lists->numfree = 0; - for(i = 0; i != lists->memsize; ++i) { - if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i]; - } - lists->nextfree = 0; - } - - result = lists->freelist[lists->nextfree++]; - result->weight = weight; - result->index = index; - result->tail = tail; - return result; -} - -/*sort the leaves with stable mergesort*/ -static void bpmnode_sort(BPMNode* leaves, size_t num) { - BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num); - size_t width, counter = 0; - for(width = 1; width < num; width *= 2) { - BPMNode* a = (counter & 1) ? mem : leaves; - BPMNode* b = (counter & 1) ? leaves : mem; - size_t p; - for(p = 0; p < num; p += 2 * width) { - size_t q = (p + width > num) ? num : (p + width); - size_t r = (p + 2 * width > num) ? num : (p + 2 * width); - size_t i = p, j = q, k; - for(k = p; k < r; k++) { - if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++]; - else b[k] = a[j++]; - } - } - counter++; - } - if(counter & 1) lodepng_memcpy(leaves, mem, sizeof(*leaves) * num); - lodepng_free(mem); -} - -/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/ -static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) { - unsigned lastindex = lists->chains1[c]->index; - - if(c == 0) { - if(lastindex >= numpresent) return; - lists->chains0[c] = lists->chains1[c]; - lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0); - } else { - /*sum of the weights of the head nodes of the previous lookahead chains.*/ - int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight; - lists->chains0[c] = lists->chains1[c]; - if(lastindex < numpresent && sum > leaves[lastindex].weight) { - lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail); - return; - } - lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]); - /*in the end we are only interested in the chain of the last list, so no - need to recurse if we're at the last one (this gives measurable speedup)*/ - if(num + 1 < (int)(2 * numpresent - 2)) { - boundaryPM(lists, leaves, numpresent, c - 1, num); - boundaryPM(lists, leaves, numpresent, c - 1, num); - } - } -} - -unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, - size_t numcodes, unsigned maxbitlen) { - unsigned error = 0; - unsigned i; - size_t numpresent = 0; /*number of symbols with non-zero frequency*/ - BPMNode* leaves; /*the symbols, only those with > 0 frequency*/ - - if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ - if((1u << maxbitlen) < (unsigned)numcodes) return 80; /*error: represent all symbols*/ - - leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves)); - if(!leaves) return 83; /*alloc fail*/ - - for(i = 0; i != numcodes; ++i) { - if(frequencies[i] > 0) { - leaves[numpresent].weight = (int)frequencies[i]; - leaves[numpresent].index = i; - ++numpresent; - } - } - - lodepng_memset(lengths, 0, numcodes * sizeof(*lengths)); - - /*ensure at least two present symbols. There should be at least one symbol - according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To - make these work as well ensure there are at least two symbols. The - Package-Merge code below also doesn't work correctly if there's only one - symbol, it'd give it the theoretical 0 bits but in practice zlib wants 1 bit*/ - if(numpresent == 0) { - lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/ - } else if(numpresent == 1) { - lengths[leaves[0].index] = 1; - lengths[leaves[0].index == 0 ? 1 : 0] = 1; - } else { - BPMLists lists; - BPMNode* node; - - bpmnode_sort(leaves, numpresent); - - lists.listsize = maxbitlen; - lists.memsize = 2 * maxbitlen * (maxbitlen + 1); - lists.nextfree = 0; - lists.numfree = lists.memsize; - lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory)); - lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*)); - lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); - lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); - if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/ - - if(!error) { - for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i]; - - bpmnode_create(&lists, leaves[0].weight, 1, 0); - bpmnode_create(&lists, leaves[1].weight, 2, 0); - - for(i = 0; i != lists.listsize; ++i) { - lists.chains0[i] = &lists.memory[0]; - lists.chains1[i] = &lists.memory[1]; - } - - /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/ - for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i); - - for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) { - for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index]; - } - } - - lodepng_free(lists.memory); - lodepng_free(lists.freelist); - lodepng_free(lists.chains0); - lodepng_free(lists.chains1); - } - - lodepng_free(leaves); - return error; -} - -/*Create the Huffman tree given the symbol frequencies*/ -static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies, - size_t mincodes, size_t numcodes, unsigned maxbitlen) { - unsigned error = 0; - while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/ - tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); - if(!tree->lengths) return 83; /*alloc fail*/ - tree->maxbitlen = maxbitlen; - tree->numcodes = (unsigned)numcodes; /*number of symbols*/ - - error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen); - if(!error) error = HuffmanTree_makeFromLengths2(tree); - return error; -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/ -static unsigned generateFixedLitLenTree(HuffmanTree* tree) { - unsigned i, error = 0; - unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); - if(!bitlen) return 83; /*alloc fail*/ - - /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ - for(i = 0; i <= 143; ++i) bitlen[i] = 8; - for(i = 144; i <= 255; ++i) bitlen[i] = 9; - for(i = 256; i <= 279; ++i) bitlen[i] = 7; - for(i = 280; i <= 287; ++i) bitlen[i] = 8; - - error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15); - - lodepng_free(bitlen); - return error; -} - -/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/ -static unsigned generateFixedDistanceTree(HuffmanTree* tree) { - unsigned i, error = 0; - unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); - if(!bitlen) return 83; /*alloc fail*/ - - /*there are 32 distance codes, but 30-31 are unused*/ - for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5; - error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15); - - lodepng_free(bitlen); - return error; -} - -#ifdef LODEPNG_COMPILE_DECODER - -/* -returns the code. The bit reader must already have been ensured at least 15 bits -*/ -static unsigned huffmanDecodeSymbol(LodePNGBitReader* reader, const HuffmanTree* codetree) { - unsigned short code = peekBits(reader, FIRSTBITS); - unsigned short l = codetree->table_len[code]; - unsigned short value = codetree->table_value[code]; - if(l <= FIRSTBITS) { - advanceBits(reader, l); - return value; - } else { - advanceBits(reader, FIRSTBITS); - value += peekBits(reader, l - FIRSTBITS); - advanceBits(reader, codetree->table_len[value] - FIRSTBITS); - return codetree->table_value[value]; - } -} -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_DECODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Inflator (Decompressor) / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*get the tree of a deflated block with fixed tree, as specified in the deflate specification -Returns error code.*/ -static unsigned getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) { - unsigned error = generateFixedLitLenTree(tree_ll); - if(error) return error; - return generateFixedDistanceTree(tree_d); -} - -/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ -static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d, - LodePNGBitReader* reader) { - /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/ - unsigned error = 0; - unsigned n, HLIT, HDIST, HCLEN, i; - - /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/ - unsigned* bitlen_ll = 0; /*lit,len code lengths*/ - unsigned* bitlen_d = 0; /*dist code lengths*/ - /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/ - unsigned* bitlen_cl = 0; - HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/ - - if(reader->bitsize - reader->bp < 14) return 49; /*error: the bit pointer is or will go past the memory*/ - ensureBits17(reader, 14); - - /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/ - HLIT = readBits(reader, 5) + 257; - /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/ - HDIST = readBits(reader, 5) + 1; - /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/ - HCLEN = readBits(reader, 4) + 4; - - bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned)); - if(!bitlen_cl) return 83 /*alloc fail*/; - - HuffmanTree_init(&tree_cl); - - while(!error) { - /*read the code length codes out of 3 * (amount of code length codes) bits*/ - if(lodepng_gtofl(reader->bp, HCLEN * 3, reader->bitsize)) { - ERROR_BREAK(50); /*error: the bit pointer is or will go past the memory*/ - } - for(i = 0; i != HCLEN; ++i) { - ensureBits9(reader, 3); /*out of bounds already checked above */ - bitlen_cl[CLCL_ORDER[i]] = readBits(reader, 3); - } - for(i = HCLEN; i != NUM_CODE_LENGTH_CODES; ++i) { - bitlen_cl[CLCL_ORDER[i]] = 0; - } - - error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7); - if(error) break; - - /*now we can use this tree to read the lengths for the tree that this function will return*/ - bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); - bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); - if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/); - lodepng_memset(bitlen_ll, 0, NUM_DEFLATE_CODE_SYMBOLS * sizeof(*bitlen_ll)); - lodepng_memset(bitlen_d, 0, NUM_DISTANCE_SYMBOLS * sizeof(*bitlen_d)); - - /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/ - i = 0; - while(i < HLIT + HDIST) { - unsigned code; - ensureBits25(reader, 22); /* up to 15 bits for huffman code, up to 7 extra bits below*/ - code = huffmanDecodeSymbol(reader, &tree_cl); - if(code <= 15) /*a length code*/ { - if(i < HLIT) bitlen_ll[i] = code; - else bitlen_d[i - HLIT] = code; - ++i; - } else if(code == 16) /*repeat previous*/ { - unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/ - unsigned value; /*set value to the previous code*/ - - if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/ - - replength += readBits(reader, 2); - - if(i < HLIT + 1) value = bitlen_ll[i - 1]; - else value = bitlen_d[i - HLIT - 1]; - /*repeat this value in the next lengths*/ - for(n = 0; n < replength; ++n) { - if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/ - if(i < HLIT) bitlen_ll[i] = value; - else bitlen_d[i - HLIT] = value; - ++i; - } - } else if(code == 17) /*repeat "0" 3-10 times*/ { - unsigned replength = 3; /*read in the bits that indicate repeat length*/ - replength += readBits(reader, 3); - - /*repeat this value in the next lengths*/ - for(n = 0; n < replength; ++n) { - if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/ - - if(i < HLIT) bitlen_ll[i] = 0; - else bitlen_d[i - HLIT] = 0; - ++i; - } - } else if(code == 18) /*repeat "0" 11-138 times*/ { - unsigned replength = 11; /*read in the bits that indicate repeat length*/ - replength += readBits(reader, 7); - - /*repeat this value in the next lengths*/ - for(n = 0; n < replength; ++n) { - if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/ - - if(i < HLIT) bitlen_ll[i] = 0; - else bitlen_d[i - HLIT] = 0; - ++i; - } - } else /*if(code == INVALIDSYMBOL)*/ { - ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ - } - /*check if any of the ensureBits above went out of bounds*/ - if(reader->bp > reader->bitsize) { - /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol - (10=no endcode, 11=wrong jump outside of tree)*/ - /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ - ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ - } - } - if(error) break; - - if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/ - - /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/ - error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15); - if(error) break; - error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15); - - break; /*end of error-while*/ - } - - lodepng_free(bitlen_cl); - lodepng_free(bitlen_ll); - lodepng_free(bitlen_d); - HuffmanTree_cleanup(&tree_cl); - - return error; -} - -/*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/ -static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader, - unsigned btype, size_t max_output_size) { - unsigned error = 0; - HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/ - HuffmanTree tree_d; /*the huffman tree for distance codes*/ - const size_t reserved_size = 260; /* must be at least 258 for max length, and a few extra for adding a few extra literals */ - int done = 0; - - if(!ucvector_reserve(out, out->size + reserved_size)) return 83; /*alloc fail*/ - - HuffmanTree_init(&tree_ll); - HuffmanTree_init(&tree_d); - - if(btype == 1) error = getTreeInflateFixed(&tree_ll, &tree_d); - else /*if(btype == 2)*/ error = getTreeInflateDynamic(&tree_ll, &tree_d, reader); - - - while(!error && !done) /*decode all symbols until end reached, breaks at end code*/ { - /*code_ll is literal, length or end code*/ - unsigned code_ll; - /* ensure enough bits for 2 huffman code reads (15 bits each): if the first is a literal, a second literal is read at once. This - appears to be slightly faster, than ensuring 20 bits here for 1 huffman symbol and the potential 5 extra bits for the length symbol.*/ - ensureBits32(reader, 30); - code_ll = huffmanDecodeSymbol(reader, &tree_ll); - if(code_ll <= 255) { - /*slightly faster code path if multiple literals in a row*/ - out->data[out->size++] = (unsigned char)code_ll; - code_ll = huffmanDecodeSymbol(reader, &tree_ll); - } - if(code_ll <= 255) /*literal symbol*/ { - out->data[out->size++] = (unsigned char)code_ll; - } else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ { - unsigned code_d, distance; - unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/ - size_t start, backward, length; - - /*part 1: get length base*/ - length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX]; - - /*part 2: get extra bits and add the value of that to length*/ - numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX]; - if(numextrabits_l != 0) { - /* bits already ensured above */ - ensureBits25(reader, 5); - length += readBits(reader, numextrabits_l); - } - - /*part 3: get distance code*/ - ensureBits32(reader, 28); /* up to 15 for the huffman symbol, up to 13 for the extra bits */ - code_d = huffmanDecodeSymbol(reader, &tree_d); - if(code_d > 29) { - if(code_d <= 31) { - ERROR_BREAK(18); /*error: invalid distance code (30-31 are never used)*/ - } else /* if(code_d == INVALIDSYMBOL) */{ - ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ - } - } - distance = DISTANCEBASE[code_d]; - - /*part 4: get extra bits from distance*/ - numextrabits_d = DISTANCEEXTRA[code_d]; - if(numextrabits_d != 0) { - /* bits already ensured above */ - distance += readBits(reader, numextrabits_d); - } - - /*part 5: fill in all the out[n] values based on the length and dist*/ - start = out->size; - if(distance > start) ERROR_BREAK(52); /*too long backward distance*/ - backward = start - distance; - - out->size += length; - if(distance < length) { - size_t forward; - lodepng_memcpy(out->data + start, out->data + backward, distance); - start += distance; - for(forward = distance; forward < length; ++forward) { - out->data[start++] = out->data[backward++]; - } - } else { - lodepng_memcpy(out->data + start, out->data + backward, length); - } - } else if(code_ll == 256) { - done = 1; /*end code, finish the loop*/ - } else /*if(code_ll == INVALIDSYMBOL)*/ { - ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ - } - if(out->allocsize - out->size < reserved_size) { - if(!ucvector_reserve(out, out->size + reserved_size)) ERROR_BREAK(83); /*alloc fail*/ - } - /*check if any of the ensureBits above went out of bounds*/ - if(reader->bp > reader->bitsize) { - /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol - (10=no endcode, 11=wrong jump outside of tree)*/ - /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ - ERROR_BREAK(51); /*error, bit pointer jumps past memory*/ - } - if(max_output_size && out->size > max_output_size) { - ERROR_BREAK(109); /*error, larger than max size*/ - } - } - - HuffmanTree_cleanup(&tree_ll); - HuffmanTree_cleanup(&tree_d); - - return error; -} - -static unsigned inflateNoCompression(ucvector* out, LodePNGBitReader* reader, - const LodePNGDecompressSettings* settings) { - size_t bytepos; - size_t size = reader->size; - unsigned LEN, NLEN, error = 0; - - /*go to first boundary of byte*/ - bytepos = (reader->bp + 7u) >> 3u; - - /*read LEN (2 bytes) and NLEN (2 bytes)*/ - if(bytepos + 4 >= size) return 52; /*error, bit pointer will jump past memory*/ - LEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); bytepos += 2; - NLEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); bytepos += 2; - - /*check if 16-bit NLEN is really the one's complement of LEN*/ - if(!settings->ignore_nlen && LEN + NLEN != 65535) { - return 21; /*error: NLEN is not one's complement of LEN*/ - } - - if(!ucvector_resize(out, out->size + LEN)) return 83; /*alloc fail*/ - - /*read the literal data: LEN bytes are now stored in the out buffer*/ - if(bytepos + LEN > size) return 23; /*error: reading outside of in buffer*/ - - /*out->data can be NULL (when LEN is zero), and arithmetics on NULL ptr is undefined*/ - if (LEN) { - lodepng_memcpy(out->data + out->size - LEN, reader->data + bytepos, LEN); - bytepos += LEN; - } - - reader->bp = bytepos << 3u; - - return error; -} - -static unsigned lodepng_inflatev(ucvector* out, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) { - unsigned BFINAL = 0; - LodePNGBitReader reader; - unsigned error = LodePNGBitReader_init(&reader, in, insize); - - if(error) return error; - - while(!BFINAL) { - unsigned BTYPE; - if(reader.bitsize - reader.bp < 3) return 52; /*error, bit pointer will jump past memory*/ - ensureBits9(&reader, 3); - BFINAL = readBits(&reader, 1); - BTYPE = readBits(&reader, 2); - - if(BTYPE == 3) return 20; /*error: invalid BTYPE*/ - else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/ - else error = inflateHuffmanBlock(out, &reader, BTYPE, settings->max_output_size); /*compression, BTYPE 01 or 10*/ - if(!error && settings->max_output_size && out->size > settings->max_output_size) error = 109; - if(error) break; - } - - return error; -} - -unsigned lodepng_inflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) { - ucvector v = ucvector_init(*out, *outsize); - unsigned error = lodepng_inflatev(&v, in, insize, settings); - *out = v.data; - *outsize = v.size; - return error; -} - -static unsigned inflatev(ucvector* out, const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) { - if(settings->custom_inflate) { - unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings); - out->allocsize = out->size; - if(error) { - /*the custom inflate is allowed to have its own error codes, however, we translate it to code 110*/ - error = 110; - /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ - if(settings->max_output_size && out->size > settings->max_output_size) error = 109; - } - return error; - } else { - return lodepng_inflatev(out, in, insize, settings); - } -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Deflator (Compressor) / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258; - -/*search the index in the array, that has the largest value smaller than or equal to the given value, -given array must be sorted (if no value is smaller, it returns the size of the given array)*/ -static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) { - /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/ - size_t left = 1; - size_t right = array_size - 1; - - while(left <= right) { - size_t mid = (left + right) >> 1; - if(array[mid] >= value) right = mid - 1; - else left = mid + 1; - } - if(left >= array_size || array[left] > value) left--; - return left; -} - -static void addLengthDistance(uivector* values, size_t length, size_t distance) { - /*values in encoded vector are those used by deflate: - 0-255: literal bytes - 256: end - 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) - 286-287: invalid*/ - - unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); - unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); - unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); - unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); - - size_t pos = values->size; - /*TODO: return error when this fails (out of memory)*/ - unsigned ok = uivector_resize(values, values->size + 4); - if(ok) { - values->data[pos + 0] = length_code + FIRST_LENGTH_CODE_INDEX; - values->data[pos + 1] = extra_length; - values->data[pos + 2] = dist_code; - values->data[pos + 3] = extra_distance; - } -} - -/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3 -bytes as input because 3 is the minimum match length for deflate*/ -static const unsigned HASH_NUM_VALUES = 65536; -static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/ - -typedef struct Hash { - int* head; /*hash value to head circular pos - can be outdated if went around window*/ - /*circular pos to prev circular pos*/ - unsigned short* chain; - int* val; /*circular pos to hash value*/ - - /*TODO: do this not only for zeros but for any repeated byte. However for PNG - it's always going to be the zeros that dominate, so not important for PNG*/ - int* headz; /*similar to head, but for chainz*/ - unsigned short* chainz; /*those with same amount of zeros*/ - unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/ -} Hash; - -static unsigned hash_init(Hash* hash, unsigned windowsize) { - unsigned i; - hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES); - hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize); - hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); - - hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); - hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1)); - hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); - - if(!hash->head || !hash->chain || !hash->val || !hash->headz|| !hash->chainz || !hash->zeros) { - return 83; /*alloc fail*/ - } - - /*initialize hash table*/ - for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1; - for(i = 0; i != windowsize; ++i) hash->val[i] = -1; - for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/ - - for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1; - for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/ - - return 0; -} - -static void hash_cleanup(Hash* hash) { - lodepng_free(hash->head); - lodepng_free(hash->val); - lodepng_free(hash->chain); - - lodepng_free(hash->zeros); - lodepng_free(hash->headz); - lodepng_free(hash->chainz); -} - - - -static unsigned getHash(const unsigned char* data, size_t size, size_t pos) { - unsigned result = 0; - if(pos + 2 < size) { - /*A simple shift and xor hash is used. Since the data of PNGs is dominated - by zeroes due to the filters, a better hash does not have a significant - effect on speed in traversing the chain, and causes more time spend on - calculating the hash.*/ - result ^= ((unsigned)data[pos + 0] << 0u); - result ^= ((unsigned)data[pos + 1] << 4u); - result ^= ((unsigned)data[pos + 2] << 8u); - } else { - size_t amount, i; - if(pos >= size) return 0; - amount = size - pos; - for(i = 0; i != amount; ++i) result ^= ((unsigned)data[pos + i] << (i * 8u)); - } - return result & HASH_BIT_MASK; -} - -static unsigned countZeros(const unsigned char* data, size_t size, size_t pos) { - const unsigned char* start = data + pos; - const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH; - if(end > data + size) end = data + size; - data = start; - while(data != end && *data == 0) ++data; - /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/ - return (unsigned)(data - start); -} - -/*wpos = pos & (windowsize - 1)*/ -static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros) { - hash->val[wpos] = (int)hashval; - if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval]; - hash->head[hashval] = (int)wpos; - - hash->zeros[wpos] = numzeros; - if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros]; - hash->headz[numzeros] = (int)wpos; -} - -/* -LZ77-encode the data. Return value is error code. The input are raw bytes, the output -is in the form of unsigned integers with codes representing for example literal bytes, or -length/distance pairs. -It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a -sliding window (of windowsize) is used, and all past bytes in that window can be used as -the "dictionary". A brute force search through all possible distances would be slow, and -this hash technique is one out of several ways to speed this up. -*/ -static unsigned encodeLZ77(uivector* out, Hash* hash, - const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize, - unsigned minmatch, unsigned nicematch, unsigned lazymatching) { - size_t pos; - unsigned i, error = 0; - /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/ - unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8u; - unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64; - - unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/ - unsigned numzeros = 0; - - unsigned offset; /*the offset represents the distance in LZ77 terminology*/ - unsigned length; - unsigned lazy = 0; - unsigned lazylength = 0, lazyoffset = 0; - unsigned hashval; - unsigned current_offset, current_length; - unsigned prev_offset; - const unsigned char *lastptr, *foreptr, *backptr; - unsigned hashpos; - - if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/ - if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/ - - if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH; - - for(pos = inpos; pos < insize; ++pos) { - size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/ - unsigned chainlength = 0; - - hashval = getHash(in, insize, pos); - - if(usezeros && hashval == 0) { - if(numzeros == 0) numzeros = countZeros(in, insize, pos); - else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; - } else { - numzeros = 0; - } - - updateHashChain(hash, wpos, hashval, numzeros); - - /*the length and offset found for the current position*/ - length = 0; - offset = 0; - - hashpos = hash->chain[wpos]; - - lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH]; - - /*search for the longest string*/ - prev_offset = 0; - for(;;) { - if(chainlength++ >= maxchainlength) break; - current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize); - - if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/ - prev_offset = current_offset; - if(current_offset > 0) { - /*test the next characters*/ - foreptr = &in[pos]; - backptr = &in[pos - current_offset]; - - /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/ - if(numzeros >= 3) { - unsigned skip = hash->zeros[hashpos]; - if(skip > numzeros) skip = numzeros; - backptr += skip; - foreptr += skip; - } - - while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/ { - ++backptr; - ++foreptr; - } - current_length = (unsigned)(foreptr - &in[pos]); - - if(current_length > length) { - length = current_length; /*the longest length*/ - offset = current_offset; /*the offset that is related to this longest length*/ - /*jump out once a length of max length is found (speed gain). This also jumps - out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/ - if(current_length >= nicematch) break; - } - } - - if(hashpos == hash->chain[hashpos]) break; - - if(numzeros >= 3 && length > numzeros) { - hashpos = hash->chainz[hashpos]; - if(hash->zeros[hashpos] != numzeros) break; - } else { - hashpos = hash->chain[hashpos]; - /*outdated hash value, happens if particular value was not encountered in whole last window*/ - if(hash->val[hashpos] != (int)hashval) break; - } - } - - if(lazymatching) { - if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) { - lazy = 1; - lazylength = length; - lazyoffset = offset; - continue; /*try the next byte*/ - } - if(lazy) { - lazy = 0; - if(pos == 0) ERROR_BREAK(81); - if(length > lazylength + 1) { - /*push the previous character as literal*/ - if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/); - } else { - length = lazylength; - offset = lazyoffset; - hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/ - hash->headz[numzeros] = -1; /*idem*/ - --pos; - } - } - } - if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/); - - /*encode it as length/distance pair or literal value*/ - if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ { - if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); - } else if(length < minmatch || (length == 3 && offset > 4096)) { - /*compensate for the fact that longer offsets have more extra bits, a - length of only 3 may be not worth it then*/ - if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); - } else { - addLengthDistance(out, length, offset); - for(i = 1; i < length; ++i) { - ++pos; - wpos = pos & (windowsize - 1); - hashval = getHash(in, insize, pos); - if(usezeros && hashval == 0) { - if(numzeros == 0) numzeros = countZeros(in, insize, pos); - else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; - } else { - numzeros = 0; - } - updateHashChain(hash, wpos, hashval, numzeros); - } - } - } /*end of the loop through each character of input*/ - - return error; -} - -/* /////////////////////////////////////////////////////////////////////////// */ - -static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) { - /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, - 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ - - size_t i, numdeflateblocks = (datasize + 65534u) / 65535u; - unsigned datapos = 0; - for(i = 0; i != numdeflateblocks; ++i) { - unsigned BFINAL, BTYPE, LEN, NLEN; - unsigned char firstbyte; - size_t pos = out->size; - - BFINAL = (i == numdeflateblocks - 1); - BTYPE = 0; - - LEN = 65535; - if(datasize - datapos < 65535u) LEN = (unsigned)datasize - datapos; - NLEN = 65535 - LEN; - - if(!ucvector_resize(out, out->size + LEN + 5)) return 83; /*alloc fail*/ - - firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1u) << 1u) + ((BTYPE & 2u) << 1u)); - out->data[pos + 0] = firstbyte; - out->data[pos + 1] = (unsigned char)(LEN & 255); - out->data[pos + 2] = (unsigned char)(LEN >> 8u); - out->data[pos + 3] = (unsigned char)(NLEN & 255); - out->data[pos + 4] = (unsigned char)(NLEN >> 8u); - lodepng_memcpy(out->data + pos + 5, data + datapos, LEN); - datapos += LEN; - } - - return 0; -} - -/* -write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees. -tree_ll: the tree for lit and len codes. -tree_d: the tree for distance codes. -*/ -static void writeLZ77data(LodePNGBitWriter* writer, const uivector* lz77_encoded, - const HuffmanTree* tree_ll, const HuffmanTree* tree_d) { - size_t i = 0; - for(i = 0; i != lz77_encoded->size; ++i) { - unsigned val = lz77_encoded->data[i]; - writeBitsReversed(writer, tree_ll->codes[val], tree_ll->lengths[val]); - if(val > 256) /*for a length code, 3 more things have to be added*/ { - unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; - unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; - unsigned length_extra_bits = lz77_encoded->data[++i]; - - unsigned distance_code = lz77_encoded->data[++i]; - - unsigned distance_index = distance_code; - unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; - unsigned distance_extra_bits = lz77_encoded->data[++i]; - - writeBits(writer, length_extra_bits, n_length_extra_bits); - writeBitsReversed(writer, tree_d->codes[distance_code], tree_d->lengths[distance_code]); - writeBits(writer, distance_extra_bits, n_distance_extra_bits); - } - } -} - -/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/ -static unsigned deflateDynamic(LodePNGBitWriter* writer, Hash* hash, - const unsigned char* data, size_t datapos, size_t dataend, - const LodePNGCompressSettings* settings, unsigned final) { - unsigned error = 0; - - /* - A block is compressed as follows: The PNG data is lz77 encoded, resulting in - literal bytes and length/distance pairs. This is then huffman compressed with - two huffman trees. One huffman tree is used for the lit and len values ("ll"), - another huffman tree is used for the dist values ("d"). These two trees are - stored using their code lengths, and to compress even more these code lengths - are also run-length encoded and huffman compressed. This gives a huffman tree - of code lengths "cl". The code lengths used to describe this third tree are - the code length code lengths ("clcl"). - */ - - /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/ - uivector lz77_encoded; - HuffmanTree tree_ll; /*tree for lit,len values*/ - HuffmanTree tree_d; /*tree for distance codes*/ - HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/ - unsigned* frequencies_ll = 0; /*frequency of lit,len codes*/ - unsigned* frequencies_d = 0; /*frequency of dist codes*/ - unsigned* frequencies_cl = 0; /*frequency of code length codes*/ - unsigned* bitlen_lld = 0; /*lit,len,dist code lengths (int bits), literally (without repeat codes).*/ - unsigned* bitlen_lld_e = 0; /*bitlen_lld encoded with repeat codes (this is a rudimentary run length compression)*/ - size_t datasize = dataend - datapos; - - /* - If we could call "bitlen_cl" the the code length code lengths ("clcl"), that is the bit lengths of codes to represent - tree_cl in CLCL_ORDER, then due to the huffman compression of huffman tree representations ("two levels"), there are - some analogies: - bitlen_lld is to tree_cl what data is to tree_ll and tree_d. - bitlen_lld_e is to bitlen_lld what lz77_encoded is to data. - bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded. - */ - - unsigned BFINAL = final; - size_t i; - size_t numcodes_ll, numcodes_d, numcodes_lld, numcodes_lld_e, numcodes_cl; - unsigned HLIT, HDIST, HCLEN; - - uivector_init(&lz77_encoded); - HuffmanTree_init(&tree_ll); - HuffmanTree_init(&tree_d); - HuffmanTree_init(&tree_cl); - /* could fit on stack, but >1KB is on the larger side so allocate instead */ - frequencies_ll = (unsigned*)lodepng_malloc(286 * sizeof(*frequencies_ll)); - frequencies_d = (unsigned*)lodepng_malloc(30 * sizeof(*frequencies_d)); - frequencies_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl)); - - if(!frequencies_ll || !frequencies_d || !frequencies_cl) error = 83; /*alloc fail*/ - - /*This while loop never loops due to a break at the end, it is here to - allow breaking out of it to the cleanup phase on error conditions.*/ - while(!error) { - lodepng_memset(frequencies_ll, 0, 286 * sizeof(*frequencies_ll)); - lodepng_memset(frequencies_d, 0, 30 * sizeof(*frequencies_d)); - lodepng_memset(frequencies_cl, 0, NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl)); - - if(settings->use_lz77) { - error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, - settings->minmatch, settings->nicematch, settings->lazymatching); - if(error) break; - } else { - if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/); - for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/ - } - - /*Count the frequencies of lit, len and dist codes*/ - for(i = 0; i != lz77_encoded.size; ++i) { - unsigned symbol = lz77_encoded.data[i]; - ++frequencies_ll[symbol]; - if(symbol > 256) { - unsigned dist = lz77_encoded.data[i + 2]; - ++frequencies_d[dist]; - i += 3; - } - } - frequencies_ll[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ - - /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/ - error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll, 257, 286, 15); - if(error) break; - /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/ - error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d, 2, 30, 15); - if(error) break; - - numcodes_ll = LODEPNG_MIN(tree_ll.numcodes, 286); - numcodes_d = LODEPNG_MIN(tree_d.numcodes, 30); - /*store the code lengths of both generated trees in bitlen_lld*/ - numcodes_lld = numcodes_ll + numcodes_d; - bitlen_lld = (unsigned*)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld)); - /*numcodes_lld_e never needs more size than bitlen_lld*/ - bitlen_lld_e = (unsigned*)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld_e)); - if(!bitlen_lld || !bitlen_lld_e) ERROR_BREAK(83); /*alloc fail*/ - numcodes_lld_e = 0; - - for(i = 0; i != numcodes_ll; ++i) bitlen_lld[i] = tree_ll.lengths[i]; - for(i = 0; i != numcodes_d; ++i) bitlen_lld[numcodes_ll + i] = tree_d.lengths[i]; - - /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times), - 17 (3-10 zeroes), 18 (11-138 zeroes)*/ - for(i = 0; i != numcodes_lld; ++i) { - unsigned j = 0; /*amount of repetitions*/ - while(i + j + 1 < numcodes_lld && bitlen_lld[i + j + 1] == bitlen_lld[i]) ++j; - - if(bitlen_lld[i] == 0 && j >= 2) /*repeat code for zeroes*/ { - ++j; /*include the first zero*/ - if(j <= 10) /*repeat code 17 supports max 10 zeroes*/ { - bitlen_lld_e[numcodes_lld_e++] = 17; - bitlen_lld_e[numcodes_lld_e++] = j - 3; - } else /*repeat code 18 supports max 138 zeroes*/ { - if(j > 138) j = 138; - bitlen_lld_e[numcodes_lld_e++] = 18; - bitlen_lld_e[numcodes_lld_e++] = j - 11; - } - i += (j - 1); - } else if(j >= 3) /*repeat code for value other than zero*/ { - size_t k; - unsigned num = j / 6u, rest = j % 6u; - bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i]; - for(k = 0; k < num; ++k) { - bitlen_lld_e[numcodes_lld_e++] = 16; - bitlen_lld_e[numcodes_lld_e++] = 6 - 3; - } - if(rest >= 3) { - bitlen_lld_e[numcodes_lld_e++] = 16; - bitlen_lld_e[numcodes_lld_e++] = rest - 3; - } - else j -= rest; - i += j; - } else /*too short to benefit from repeat code*/ { - bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i]; - } - } - - /*generate tree_cl, the huffmantree of huffmantrees*/ - for(i = 0; i != numcodes_lld_e; ++i) { - ++frequencies_cl[bitlen_lld_e[i]]; - /*after a repeat code come the bits that specify the number of repetitions, - those don't need to be in the frequencies_cl calculation*/ - if(bitlen_lld_e[i] >= 16) ++i; - } - - error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl, - NUM_CODE_LENGTH_CODES, NUM_CODE_LENGTH_CODES, 7); - if(error) break; - - /*compute amount of code-length-code-lengths to output*/ - numcodes_cl = NUM_CODE_LENGTH_CODES; - /*trim zeros at the end (using CLCL_ORDER), but minimum size must be 4 (see HCLEN below)*/ - while(numcodes_cl > 4u && tree_cl.lengths[CLCL_ORDER[numcodes_cl - 1u]] == 0) { - numcodes_cl--; - } - - /* - Write everything into the output - - After the BFINAL and BTYPE, the dynamic block consists out of the following: - - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN - - (HCLEN+4)*3 bits code lengths of code length alphabet - - HLIT + 257 code lengths of lit/length alphabet (encoded using the code length - alphabet, + possible repetition codes 16, 17, 18) - - HDIST + 1 code lengths of distance alphabet (encoded using the code length - alphabet, + possible repetition codes 16, 17, 18) - - compressed data - - 256 (end code) - */ - - /*Write block type*/ - writeBits(writer, BFINAL, 1); - writeBits(writer, 0, 1); /*first bit of BTYPE "dynamic"*/ - writeBits(writer, 1, 1); /*second bit of BTYPE "dynamic"*/ - - /*write the HLIT, HDIST and HCLEN values*/ - /*all three sizes take trimmed ending zeroes into account, done either by HuffmanTree_makeFromFrequencies - or in the loop for numcodes_cl above, which saves space. */ - HLIT = (unsigned)(numcodes_ll - 257); - HDIST = (unsigned)(numcodes_d - 1); - HCLEN = (unsigned)(numcodes_cl - 4); - writeBits(writer, HLIT, 5); - writeBits(writer, HDIST, 5); - writeBits(writer, HCLEN, 4); - - /*write the code lengths of the code length alphabet ("bitlen_cl")*/ - for(i = 0; i != numcodes_cl; ++i) writeBits(writer, tree_cl.lengths[CLCL_ORDER[i]], 3); - - /*write the lengths of the lit/len AND the dist alphabet*/ - for(i = 0; i != numcodes_lld_e; ++i) { - writeBitsReversed(writer, tree_cl.codes[bitlen_lld_e[i]], tree_cl.lengths[bitlen_lld_e[i]]); - /*extra bits of repeat codes*/ - if(bitlen_lld_e[i] == 16) writeBits(writer, bitlen_lld_e[++i], 2); - else if(bitlen_lld_e[i] == 17) writeBits(writer, bitlen_lld_e[++i], 3); - else if(bitlen_lld_e[i] == 18) writeBits(writer, bitlen_lld_e[++i], 7); - } - - /*write the compressed data symbols*/ - writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d); - /*error: the length of the end code 256 must be larger than 0*/ - if(tree_ll.lengths[256] == 0) ERROR_BREAK(64); - - /*write the end code*/ - writeBitsReversed(writer, tree_ll.codes[256], tree_ll.lengths[256]); - - break; /*end of error-while*/ - } - - /*cleanup*/ - uivector_cleanup(&lz77_encoded); - HuffmanTree_cleanup(&tree_ll); - HuffmanTree_cleanup(&tree_d); - HuffmanTree_cleanup(&tree_cl); - lodepng_free(frequencies_ll); - lodepng_free(frequencies_d); - lodepng_free(frequencies_cl); - lodepng_free(bitlen_lld); - lodepng_free(bitlen_lld_e); - - return error; -} - -static unsigned deflateFixed(LodePNGBitWriter* writer, Hash* hash, - const unsigned char* data, - size_t datapos, size_t dataend, - const LodePNGCompressSettings* settings, unsigned final) { - HuffmanTree tree_ll; /*tree for literal values and length codes*/ - HuffmanTree tree_d; /*tree for distance codes*/ - - unsigned BFINAL = final; - unsigned error = 0; - size_t i; - - HuffmanTree_init(&tree_ll); - HuffmanTree_init(&tree_d); - - error = generateFixedLitLenTree(&tree_ll); - if(!error) error = generateFixedDistanceTree(&tree_d); - - if(!error) { - writeBits(writer, BFINAL, 1); - writeBits(writer, 1, 1); /*first bit of BTYPE*/ - writeBits(writer, 0, 1); /*second bit of BTYPE*/ - - if(settings->use_lz77) /*LZ77 encoded*/ { - uivector lz77_encoded; - uivector_init(&lz77_encoded); - error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, - settings->minmatch, settings->nicematch, settings->lazymatching); - if(!error) writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d); - uivector_cleanup(&lz77_encoded); - } else /*no LZ77, but still will be Huffman compressed*/ { - for(i = datapos; i < dataend; ++i) { - writeBitsReversed(writer, tree_ll.codes[data[i]], tree_ll.lengths[data[i]]); - } - } - /*add END code*/ - if(!error) writeBitsReversed(writer,tree_ll.codes[256], tree_ll.lengths[256]); - } - - /*cleanup*/ - HuffmanTree_cleanup(&tree_ll); - HuffmanTree_cleanup(&tree_d); - - return error; -} - -static unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings) { - unsigned error = 0; - size_t i, blocksize, numdeflateblocks; - Hash hash; - LodePNGBitWriter writer; - - LodePNGBitWriter_init(&writer, out); - - if(settings->btype > 2) return 61; - else if(settings->btype == 0) return deflateNoCompression(out, in, insize); - else if(settings->btype == 1) blocksize = insize; - else /*if(settings->btype == 2)*/ { - /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/ - blocksize = insize / 8u + 8; - if(blocksize < 65536) blocksize = 65536; - if(blocksize > 262144) blocksize = 262144; - } - - numdeflateblocks = (insize + blocksize - 1) / blocksize; - if(numdeflateblocks == 0) numdeflateblocks = 1; - - error = hash_init(&hash, settings->windowsize); - - if(!error) { - for(i = 0; i != numdeflateblocks && !error; ++i) { - unsigned final = (i == numdeflateblocks - 1); - size_t start = i * blocksize; - size_t end = start + blocksize; - if(end > insize) end = insize; - - if(settings->btype == 1) error = deflateFixed(&writer, &hash, in, start, end, settings, final); - else if(settings->btype == 2) error = deflateDynamic(&writer, &hash, in, start, end, settings, final); - } - } - - hash_cleanup(&hash); - - return error; -} - -unsigned lodepng_deflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings) { - ucvector v = ucvector_init(*out, *outsize); - unsigned error = lodepng_deflatev(&v, in, insize, settings); - *out = v.data; - *outsize = v.size; - return error; -} - -static unsigned deflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings) { - if(settings->custom_deflate) { - unsigned error = settings->custom_deflate(out, outsize, in, insize, settings); - /*the custom deflate is allowed to have its own error codes, however, we translate it to code 111*/ - return error ? 111 : 0; - } else { - return lodepng_deflate(out, outsize, in, insize, settings); - } -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Adler32 / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) { - unsigned s1 = adler & 0xffffu; - unsigned s2 = (adler >> 16u) & 0xffffu; - - while(len != 0u) { - unsigned i; - /*at least 5552 sums can be done before the sums overflow, saving a lot of module divisions*/ - unsigned amount = len > 5552u ? 5552u : len; - len -= amount; - for(i = 0; i != amount; ++i) { - s1 += (*data++); - s2 += s1; - } - s1 %= 65521u; - s2 %= 65521u; - } - - return (s2 << 16u) | s1; -} - -/*Return the adler32 of the bytes data[0..len-1]*/ -static unsigned adler32(const unsigned char* data, unsigned len) { - return update_adler32(1u, data, len); -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Zlib / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_DECODER - -static unsigned lodepng_zlib_decompressv(ucvector* out, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) { - unsigned error = 0; - unsigned CM, CINFO, FDICT; - - if(insize < 2) return 53; /*error, size of zlib data too small*/ - /*read information from zlib header*/ - if((in[0] * 256 + in[1]) % 31 != 0) { - /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/ - return 24; - } - - CM = in[0] & 15; - CINFO = (in[0] >> 4) & 15; - /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/ - FDICT = (in[1] >> 5) & 1; - /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/ - - if(CM != 8 || CINFO > 7) { - /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/ - return 25; - } - if(FDICT != 0) { - /*error: the specification of PNG says about the zlib stream: - "The additional flags shall not specify a preset dictionary."*/ - return 26; - } - - error = inflatev(out, in + 2, insize - 2, settings); - if(error) return error; - - if(!settings->ignore_adler32) { - unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]); - unsigned checksum = adler32(out->data, (unsigned)(out->size)); - if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/ - } - - return 0; /*no error*/ -} - - -unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGDecompressSettings* settings) { - ucvector v = ucvector_init(*out, *outsize); - unsigned error = lodepng_zlib_decompressv(&v, in, insize, settings); - *out = v.data; - *outsize = v.size; - return error; -} - -/*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */ -static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size, - const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) { - unsigned error; - if(settings->custom_zlib) { - error = settings->custom_zlib(out, outsize, in, insize, settings); - if(error) { - /*the custom zlib is allowed to have its own error codes, however, we translate it to code 110*/ - error = 110; - /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ - if(settings->max_output_size && *outsize > settings->max_output_size) error = 109; - } - } else { - ucvector v = ucvector_init(*out, *outsize); - if(expected_size) { - /*reserve the memory to avoid intermediate reallocations*/ - ucvector_resize(&v, *outsize + expected_size); - v.size = *outsize; - } - error = lodepng_zlib_decompressv(&v, in, insize, settings); - *out = v.data; - *outsize = v.size; - } - return error; -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER - -unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGCompressSettings* settings) { - size_t i; - unsigned error; - unsigned char* deflatedata = 0; - size_t deflatesize = 0; - - error = deflate(&deflatedata, &deflatesize, in, insize, settings); - - *out = NULL; - *outsize = 0; - if(!error) { - *outsize = deflatesize + 6; - *out = (unsigned char*)lodepng_malloc(*outsize); - if(!*out) error = 83; /*alloc fail*/ - } - - if(!error) { - unsigned ADLER32 = adler32(in, (unsigned)insize); - /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ - unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ - unsigned FLEVEL = 0; - unsigned FDICT = 0; - unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; - unsigned FCHECK = 31 - CMFFLG % 31; - CMFFLG += FCHECK; - - (*out)[0] = (unsigned char)(CMFFLG >> 8); - (*out)[1] = (unsigned char)(CMFFLG & 255); - for(i = 0; i != deflatesize; ++i) (*out)[i + 2] = deflatedata[i]; - lodepng_set32bitInt(&(*out)[*outsize - 4], ADLER32); - } - - lodepng_free(deflatedata); - return error; -} - -/* compress using the default or custom zlib function */ -static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGCompressSettings* settings) { - if(settings->custom_zlib) { - unsigned error = settings->custom_zlib(out, outsize, in, insize, settings); - /*the custom zlib is allowed to have its own error codes, however, we translate it to code 111*/ - return error ? 111 : 0; - } else { - return lodepng_zlib_compress(out, outsize, in, insize, settings); - } -} - -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#else /*no LODEPNG_COMPILE_ZLIB*/ - -#ifdef LODEPNG_COMPILE_DECODER -static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size, - const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) { - if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ - (void)expected_size; - return settings->custom_zlib(out, outsize, in, insize, settings); -} -#endif /*LODEPNG_COMPILE_DECODER*/ -#ifdef LODEPNG_COMPILE_ENCODER -static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGCompressSettings* settings) { - if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ - return settings->custom_zlib(out, outsize, in, insize, settings); -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#endif /*LODEPNG_COMPILE_ZLIB*/ - -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_ENCODER - -/*this is a good tradeoff between speed and compression ratio*/ -#define DEFAULT_WINDOWSIZE 2048 - -void lodepng_compress_settings_init(LodePNGCompressSettings* settings) { - /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ - settings->btype = 2; - settings->use_lz77 = 1; - settings->windowsize = DEFAULT_WINDOWSIZE; - settings->minmatch = 3; - settings->nicematch = 128; - settings->lazymatching = 1; - - settings->custom_zlib = 0; - settings->custom_deflate = 0; - settings->custom_context = 0; -} - -const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0}; - - -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#ifdef LODEPNG_COMPILE_DECODER - -void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) { - settings->ignore_adler32 = 0; - settings->ignore_nlen = 0; - settings->max_output_size = 0; - - settings->custom_zlib = 0; - settings->custom_inflate = 0; - settings->custom_context = 0; -} - -const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0, 0}; - -#endif /*LODEPNG_COMPILE_DECODER*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // End of Zlib related code. Begin of PNG related code. // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_PNG - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / CRC32 / */ -/* ////////////////////////////////////////////////////////////////////////// */ - - -#ifdef LODEPNG_COMPILE_CRC - -static const unsigned lodepng_crc32_table0[256] = { - 0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u, - 0x0edb8832u, 0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u, - 0x1db71064u, 0x6ab020f2u, 0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u, - 0x136c9856u, 0x646ba8c0u, 0xfd62f97au, 0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u, - 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u, 0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu, - 0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u, 0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u, - 0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u, 0xcfba9599u, 0xb8bda50fu, - 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu, 0xb6662d3du, - 0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u, - 0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u, - 0x6b6b51f4u, 0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u, - 0x65b0d9c6u, 0x12b7e950u, 0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u, - 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u, 0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu, - 0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u, 0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u, - 0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u, 0x206f85b3u, 0xb966d409u, 0xce61e49fu, - 0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u, 0xb7bd5c3bu, 0xc0ba6cadu, - 0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u, 0x73dc1683u, - 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u, - 0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u, - 0xfed41b76u, 0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u, - 0xd6d6a3e8u, 0xa1d1937eu, 0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu, - 0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u, 0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u, - 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u, 0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu, - 0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u, 0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du, - 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu, 0x72076785u, 0x05005713u, - 0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u, 0x0bdbdf21u, - 0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u, - 0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u, - 0xa00ae278u, 0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu, - 0xaed16a4au, 0xd9d65adcu, 0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u, - 0xbdbdf21cu, 0xcabac28au, 0x53b39330u, 0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu, - 0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u, 0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du -}; - -static const unsigned lodepng_crc32_table1[256] = { - 0x00000000u, 0x191b3141u, 0x32366282u, 0x2b2d53c3u, 0x646cc504u, 0x7d77f445u, 0x565aa786u, 0x4f4196c7u, - 0xc8d98a08u, 0xd1c2bb49u, 0xfaefe88au, 0xe3f4d9cbu, 0xacb54f0cu, 0xb5ae7e4du, 0x9e832d8eu, 0x87981ccfu, - 0x4ac21251u, 0x53d92310u, 0x78f470d3u, 0x61ef4192u, 0x2eaed755u, 0x37b5e614u, 0x1c98b5d7u, 0x05838496u, - 0x821b9859u, 0x9b00a918u, 0xb02dfadbu, 0xa936cb9au, 0xe6775d5du, 0xff6c6c1cu, 0xd4413fdfu, 0xcd5a0e9eu, - 0x958424a2u, 0x8c9f15e3u, 0xa7b24620u, 0xbea97761u, 0xf1e8e1a6u, 0xe8f3d0e7u, 0xc3de8324u, 0xdac5b265u, - 0x5d5daeaau, 0x44469febu, 0x6f6bcc28u, 0x7670fd69u, 0x39316baeu, 0x202a5aefu, 0x0b07092cu, 0x121c386du, - 0xdf4636f3u, 0xc65d07b2u, 0xed705471u, 0xf46b6530u, 0xbb2af3f7u, 0xa231c2b6u, 0x891c9175u, 0x9007a034u, - 0x179fbcfbu, 0x0e848dbau, 0x25a9de79u, 0x3cb2ef38u, 0x73f379ffu, 0x6ae848beu, 0x41c51b7du, 0x58de2a3cu, - 0xf0794f05u, 0xe9627e44u, 0xc24f2d87u, 0xdb541cc6u, 0x94158a01u, 0x8d0ebb40u, 0xa623e883u, 0xbf38d9c2u, - 0x38a0c50du, 0x21bbf44cu, 0x0a96a78fu, 0x138d96ceu, 0x5ccc0009u, 0x45d73148u, 0x6efa628bu, 0x77e153cau, - 0xbabb5d54u, 0xa3a06c15u, 0x888d3fd6u, 0x91960e97u, 0xded79850u, 0xc7cca911u, 0xece1fad2u, 0xf5facb93u, - 0x7262d75cu, 0x6b79e61du, 0x4054b5deu, 0x594f849fu, 0x160e1258u, 0x0f152319u, 0x243870dau, 0x3d23419bu, - 0x65fd6ba7u, 0x7ce65ae6u, 0x57cb0925u, 0x4ed03864u, 0x0191aea3u, 0x188a9fe2u, 0x33a7cc21u, 0x2abcfd60u, - 0xad24e1afu, 0xb43fd0eeu, 0x9f12832du, 0x8609b26cu, 0xc94824abu, 0xd05315eau, 0xfb7e4629u, 0xe2657768u, - 0x2f3f79f6u, 0x362448b7u, 0x1d091b74u, 0x04122a35u, 0x4b53bcf2u, 0x52488db3u, 0x7965de70u, 0x607eef31u, - 0xe7e6f3feu, 0xfefdc2bfu, 0xd5d0917cu, 0xcccba03du, 0x838a36fau, 0x9a9107bbu, 0xb1bc5478u, 0xa8a76539u, - 0x3b83984bu, 0x2298a90au, 0x09b5fac9u, 0x10aecb88u, 0x5fef5d4fu, 0x46f46c0eu, 0x6dd93fcdu, 0x74c20e8cu, - 0xf35a1243u, 0xea412302u, 0xc16c70c1u, 0xd8774180u, 0x9736d747u, 0x8e2de606u, 0xa500b5c5u, 0xbc1b8484u, - 0x71418a1au, 0x685abb5bu, 0x4377e898u, 0x5a6cd9d9u, 0x152d4f1eu, 0x0c367e5fu, 0x271b2d9cu, 0x3e001cddu, - 0xb9980012u, 0xa0833153u, 0x8bae6290u, 0x92b553d1u, 0xddf4c516u, 0xc4eff457u, 0xefc2a794u, 0xf6d996d5u, - 0xae07bce9u, 0xb71c8da8u, 0x9c31de6bu, 0x852aef2au, 0xca6b79edu, 0xd37048acu, 0xf85d1b6fu, 0xe1462a2eu, - 0x66de36e1u, 0x7fc507a0u, 0x54e85463u, 0x4df36522u, 0x02b2f3e5u, 0x1ba9c2a4u, 0x30849167u, 0x299fa026u, - 0xe4c5aeb8u, 0xfdde9ff9u, 0xd6f3cc3au, 0xcfe8fd7bu, 0x80a96bbcu, 0x99b25afdu, 0xb29f093eu, 0xab84387fu, - 0x2c1c24b0u, 0x350715f1u, 0x1e2a4632u, 0x07317773u, 0x4870e1b4u, 0x516bd0f5u, 0x7a468336u, 0x635db277u, - 0xcbfad74eu, 0xd2e1e60fu, 0xf9ccb5ccu, 0xe0d7848du, 0xaf96124au, 0xb68d230bu, 0x9da070c8u, 0x84bb4189u, - 0x03235d46u, 0x1a386c07u, 0x31153fc4u, 0x280e0e85u, 0x674f9842u, 0x7e54a903u, 0x5579fac0u, 0x4c62cb81u, - 0x8138c51fu, 0x9823f45eu, 0xb30ea79du, 0xaa1596dcu, 0xe554001bu, 0xfc4f315au, 0xd7626299u, 0xce7953d8u, - 0x49e14f17u, 0x50fa7e56u, 0x7bd72d95u, 0x62cc1cd4u, 0x2d8d8a13u, 0x3496bb52u, 0x1fbbe891u, 0x06a0d9d0u, - 0x5e7ef3ecu, 0x4765c2adu, 0x6c48916eu, 0x7553a02fu, 0x3a1236e8u, 0x230907a9u, 0x0824546au, 0x113f652bu, - 0x96a779e4u, 0x8fbc48a5u, 0xa4911b66u, 0xbd8a2a27u, 0xf2cbbce0u, 0xebd08da1u, 0xc0fdde62u, 0xd9e6ef23u, - 0x14bce1bdu, 0x0da7d0fcu, 0x268a833fu, 0x3f91b27eu, 0x70d024b9u, 0x69cb15f8u, 0x42e6463bu, 0x5bfd777au, - 0xdc656bb5u, 0xc57e5af4u, 0xee530937u, 0xf7483876u, 0xb809aeb1u, 0xa1129ff0u, 0x8a3fcc33u, 0x9324fd72u -}; - -static const unsigned lodepng_crc32_table2[256] = { - 0x00000000u, 0x01c26a37u, 0x0384d46eu, 0x0246be59u, 0x0709a8dcu, 0x06cbc2ebu, 0x048d7cb2u, 0x054f1685u, - 0x0e1351b8u, 0x0fd13b8fu, 0x0d9785d6u, 0x0c55efe1u, 0x091af964u, 0x08d89353u, 0x0a9e2d0au, 0x0b5c473du, - 0x1c26a370u, 0x1de4c947u, 0x1fa2771eu, 0x1e601d29u, 0x1b2f0bacu, 0x1aed619bu, 0x18abdfc2u, 0x1969b5f5u, - 0x1235f2c8u, 0x13f798ffu, 0x11b126a6u, 0x10734c91u, 0x153c5a14u, 0x14fe3023u, 0x16b88e7au, 0x177ae44du, - 0x384d46e0u, 0x398f2cd7u, 0x3bc9928eu, 0x3a0bf8b9u, 0x3f44ee3cu, 0x3e86840bu, 0x3cc03a52u, 0x3d025065u, - 0x365e1758u, 0x379c7d6fu, 0x35dac336u, 0x3418a901u, 0x3157bf84u, 0x3095d5b3u, 0x32d36beau, 0x331101ddu, - 0x246be590u, 0x25a98fa7u, 0x27ef31feu, 0x262d5bc9u, 0x23624d4cu, 0x22a0277bu, 0x20e69922u, 0x2124f315u, - 0x2a78b428u, 0x2bbade1fu, 0x29fc6046u, 0x283e0a71u, 0x2d711cf4u, 0x2cb376c3u, 0x2ef5c89au, 0x2f37a2adu, - 0x709a8dc0u, 0x7158e7f7u, 0x731e59aeu, 0x72dc3399u, 0x7793251cu, 0x76514f2bu, 0x7417f172u, 0x75d59b45u, - 0x7e89dc78u, 0x7f4bb64fu, 0x7d0d0816u, 0x7ccf6221u, 0x798074a4u, 0x78421e93u, 0x7a04a0cau, 0x7bc6cafdu, - 0x6cbc2eb0u, 0x6d7e4487u, 0x6f38fadeu, 0x6efa90e9u, 0x6bb5866cu, 0x6a77ec5bu, 0x68315202u, 0x69f33835u, - 0x62af7f08u, 0x636d153fu, 0x612bab66u, 0x60e9c151u, 0x65a6d7d4u, 0x6464bde3u, 0x662203bau, 0x67e0698du, - 0x48d7cb20u, 0x4915a117u, 0x4b531f4eu, 0x4a917579u, 0x4fde63fcu, 0x4e1c09cbu, 0x4c5ab792u, 0x4d98dda5u, - 0x46c49a98u, 0x4706f0afu, 0x45404ef6u, 0x448224c1u, 0x41cd3244u, 0x400f5873u, 0x4249e62au, 0x438b8c1du, - 0x54f16850u, 0x55330267u, 0x5775bc3eu, 0x56b7d609u, 0x53f8c08cu, 0x523aaabbu, 0x507c14e2u, 0x51be7ed5u, - 0x5ae239e8u, 0x5b2053dfu, 0x5966ed86u, 0x58a487b1u, 0x5deb9134u, 0x5c29fb03u, 0x5e6f455au, 0x5fad2f6du, - 0xe1351b80u, 0xe0f771b7u, 0xe2b1cfeeu, 0xe373a5d9u, 0xe63cb35cu, 0xe7fed96bu, 0xe5b86732u, 0xe47a0d05u, - 0xef264a38u, 0xeee4200fu, 0xeca29e56u, 0xed60f461u, 0xe82fe2e4u, 0xe9ed88d3u, 0xebab368au, 0xea695cbdu, - 0xfd13b8f0u, 0xfcd1d2c7u, 0xfe976c9eu, 0xff5506a9u, 0xfa1a102cu, 0xfbd87a1bu, 0xf99ec442u, 0xf85cae75u, - 0xf300e948u, 0xf2c2837fu, 0xf0843d26u, 0xf1465711u, 0xf4094194u, 0xf5cb2ba3u, 0xf78d95fau, 0xf64fffcdu, - 0xd9785d60u, 0xd8ba3757u, 0xdafc890eu, 0xdb3ee339u, 0xde71f5bcu, 0xdfb39f8bu, 0xddf521d2u, 0xdc374be5u, - 0xd76b0cd8u, 0xd6a966efu, 0xd4efd8b6u, 0xd52db281u, 0xd062a404u, 0xd1a0ce33u, 0xd3e6706au, 0xd2241a5du, - 0xc55efe10u, 0xc49c9427u, 0xc6da2a7eu, 0xc7184049u, 0xc25756ccu, 0xc3953cfbu, 0xc1d382a2u, 0xc011e895u, - 0xcb4dafa8u, 0xca8fc59fu, 0xc8c97bc6u, 0xc90b11f1u, 0xcc440774u, 0xcd866d43u, 0xcfc0d31au, 0xce02b92du, - 0x91af9640u, 0x906dfc77u, 0x922b422eu, 0x93e92819u, 0x96a63e9cu, 0x976454abu, 0x9522eaf2u, 0x94e080c5u, - 0x9fbcc7f8u, 0x9e7eadcfu, 0x9c381396u, 0x9dfa79a1u, 0x98b56f24u, 0x99770513u, 0x9b31bb4au, 0x9af3d17du, - 0x8d893530u, 0x8c4b5f07u, 0x8e0de15eu, 0x8fcf8b69u, 0x8a809decu, 0x8b42f7dbu, 0x89044982u, 0x88c623b5u, - 0x839a6488u, 0x82580ebfu, 0x801eb0e6u, 0x81dcdad1u, 0x8493cc54u, 0x8551a663u, 0x8717183au, 0x86d5720du, - 0xa9e2d0a0u, 0xa820ba97u, 0xaa6604ceu, 0xaba46ef9u, 0xaeeb787cu, 0xaf29124bu, 0xad6fac12u, 0xacadc625u, - 0xa7f18118u, 0xa633eb2fu, 0xa4755576u, 0xa5b73f41u, 0xa0f829c4u, 0xa13a43f3u, 0xa37cfdaau, 0xa2be979du, - 0xb5c473d0u, 0xb40619e7u, 0xb640a7beu, 0xb782cd89u, 0xb2cddb0cu, 0xb30fb13bu, 0xb1490f62u, 0xb08b6555u, - 0xbbd72268u, 0xba15485fu, 0xb853f606u, 0xb9919c31u, 0xbcde8ab4u, 0xbd1ce083u, 0xbf5a5edau, 0xbe9834edu -}; - -static const unsigned lodepng_crc32_table3[256] = { - 0x00000000u, 0xb8bc6765u, 0xaa09c88bu, 0x12b5afeeu, 0x8f629757u, 0x37def032u, 0x256b5fdcu, 0x9dd738b9u, - 0xc5b428efu, 0x7d084f8au, 0x6fbde064u, 0xd7018701u, 0x4ad6bfb8u, 0xf26ad8ddu, 0xe0df7733u, 0x58631056u, - 0x5019579fu, 0xe8a530fau, 0xfa109f14u, 0x42acf871u, 0xdf7bc0c8u, 0x67c7a7adu, 0x75720843u, 0xcdce6f26u, - 0x95ad7f70u, 0x2d111815u, 0x3fa4b7fbu, 0x8718d09eu, 0x1acfe827u, 0xa2738f42u, 0xb0c620acu, 0x087a47c9u, - 0xa032af3eu, 0x188ec85bu, 0x0a3b67b5u, 0xb28700d0u, 0x2f503869u, 0x97ec5f0cu, 0x8559f0e2u, 0x3de59787u, - 0x658687d1u, 0xdd3ae0b4u, 0xcf8f4f5au, 0x7733283fu, 0xeae41086u, 0x525877e3u, 0x40edd80du, 0xf851bf68u, - 0xf02bf8a1u, 0x48979fc4u, 0x5a22302au, 0xe29e574fu, 0x7f496ff6u, 0xc7f50893u, 0xd540a77du, 0x6dfcc018u, - 0x359fd04eu, 0x8d23b72bu, 0x9f9618c5u, 0x272a7fa0u, 0xbafd4719u, 0x0241207cu, 0x10f48f92u, 0xa848e8f7u, - 0x9b14583du, 0x23a83f58u, 0x311d90b6u, 0x89a1f7d3u, 0x1476cf6au, 0xaccaa80fu, 0xbe7f07e1u, 0x06c36084u, - 0x5ea070d2u, 0xe61c17b7u, 0xf4a9b859u, 0x4c15df3cu, 0xd1c2e785u, 0x697e80e0u, 0x7bcb2f0eu, 0xc377486bu, - 0xcb0d0fa2u, 0x73b168c7u, 0x6104c729u, 0xd9b8a04cu, 0x446f98f5u, 0xfcd3ff90u, 0xee66507eu, 0x56da371bu, - 0x0eb9274du, 0xb6054028u, 0xa4b0efc6u, 0x1c0c88a3u, 0x81dbb01au, 0x3967d77fu, 0x2bd27891u, 0x936e1ff4u, - 0x3b26f703u, 0x839a9066u, 0x912f3f88u, 0x299358edu, 0xb4446054u, 0x0cf80731u, 0x1e4da8dfu, 0xa6f1cfbau, - 0xfe92dfecu, 0x462eb889u, 0x549b1767u, 0xec277002u, 0x71f048bbu, 0xc94c2fdeu, 0xdbf98030u, 0x6345e755u, - 0x6b3fa09cu, 0xd383c7f9u, 0xc1366817u, 0x798a0f72u, 0xe45d37cbu, 0x5ce150aeu, 0x4e54ff40u, 0xf6e89825u, - 0xae8b8873u, 0x1637ef16u, 0x048240f8u, 0xbc3e279du, 0x21e91f24u, 0x99557841u, 0x8be0d7afu, 0x335cb0cau, - 0xed59b63bu, 0x55e5d15eu, 0x47507eb0u, 0xffec19d5u, 0x623b216cu, 0xda874609u, 0xc832e9e7u, 0x708e8e82u, - 0x28ed9ed4u, 0x9051f9b1u, 0x82e4565fu, 0x3a58313au, 0xa78f0983u, 0x1f336ee6u, 0x0d86c108u, 0xb53aa66du, - 0xbd40e1a4u, 0x05fc86c1u, 0x1749292fu, 0xaff54e4au, 0x322276f3u, 0x8a9e1196u, 0x982bbe78u, 0x2097d91du, - 0x78f4c94bu, 0xc048ae2eu, 0xd2fd01c0u, 0x6a4166a5u, 0xf7965e1cu, 0x4f2a3979u, 0x5d9f9697u, 0xe523f1f2u, - 0x4d6b1905u, 0xf5d77e60u, 0xe762d18eu, 0x5fdeb6ebu, 0xc2098e52u, 0x7ab5e937u, 0x680046d9u, 0xd0bc21bcu, - 0x88df31eau, 0x3063568fu, 0x22d6f961u, 0x9a6a9e04u, 0x07bda6bdu, 0xbf01c1d8u, 0xadb46e36u, 0x15080953u, - 0x1d724e9au, 0xa5ce29ffu, 0xb77b8611u, 0x0fc7e174u, 0x9210d9cdu, 0x2aacbea8u, 0x38191146u, 0x80a57623u, - 0xd8c66675u, 0x607a0110u, 0x72cfaefeu, 0xca73c99bu, 0x57a4f122u, 0xef189647u, 0xfdad39a9u, 0x45115eccu, - 0x764dee06u, 0xcef18963u, 0xdc44268du, 0x64f841e8u, 0xf92f7951u, 0x41931e34u, 0x5326b1dau, 0xeb9ad6bfu, - 0xb3f9c6e9u, 0x0b45a18cu, 0x19f00e62u, 0xa14c6907u, 0x3c9b51beu, 0x842736dbu, 0x96929935u, 0x2e2efe50u, - 0x2654b999u, 0x9ee8defcu, 0x8c5d7112u, 0x34e11677u, 0xa9362eceu, 0x118a49abu, 0x033fe645u, 0xbb838120u, - 0xe3e09176u, 0x5b5cf613u, 0x49e959fdu, 0xf1553e98u, 0x6c820621u, 0xd43e6144u, 0xc68bceaau, 0x7e37a9cfu, - 0xd67f4138u, 0x6ec3265du, 0x7c7689b3u, 0xc4caeed6u, 0x591dd66fu, 0xe1a1b10au, 0xf3141ee4u, 0x4ba87981u, - 0x13cb69d7u, 0xab770eb2u, 0xb9c2a15cu, 0x017ec639u, 0x9ca9fe80u, 0x241599e5u, 0x36a0360bu, 0x8e1c516eu, - 0x866616a7u, 0x3eda71c2u, 0x2c6fde2cu, 0x94d3b949u, 0x090481f0u, 0xb1b8e695u, 0xa30d497bu, 0x1bb12e1eu, - 0x43d23e48u, 0xfb6e592du, 0xe9dbf6c3u, 0x516791a6u, 0xccb0a91fu, 0x740cce7au, 0x66b96194u, 0xde0506f1u -}; - -static const unsigned lodepng_crc32_table4[256] = { - 0x00000000u, 0x3d6029b0u, 0x7ac05360u, 0x47a07ad0u, 0xf580a6c0u, 0xc8e08f70u, 0x8f40f5a0u, 0xb220dc10u, - 0x30704bc1u, 0x0d106271u, 0x4ab018a1u, 0x77d03111u, 0xc5f0ed01u, 0xf890c4b1u, 0xbf30be61u, 0x825097d1u, - 0x60e09782u, 0x5d80be32u, 0x1a20c4e2u, 0x2740ed52u, 0x95603142u, 0xa80018f2u, 0xefa06222u, 0xd2c04b92u, - 0x5090dc43u, 0x6df0f5f3u, 0x2a508f23u, 0x1730a693u, 0xa5107a83u, 0x98705333u, 0xdfd029e3u, 0xe2b00053u, - 0xc1c12f04u, 0xfca106b4u, 0xbb017c64u, 0x866155d4u, 0x344189c4u, 0x0921a074u, 0x4e81daa4u, 0x73e1f314u, - 0xf1b164c5u, 0xccd14d75u, 0x8b7137a5u, 0xb6111e15u, 0x0431c205u, 0x3951ebb5u, 0x7ef19165u, 0x4391b8d5u, - 0xa121b886u, 0x9c419136u, 0xdbe1ebe6u, 0xe681c256u, 0x54a11e46u, 0x69c137f6u, 0x2e614d26u, 0x13016496u, - 0x9151f347u, 0xac31daf7u, 0xeb91a027u, 0xd6f18997u, 0x64d15587u, 0x59b17c37u, 0x1e1106e7u, 0x23712f57u, - 0x58f35849u, 0x659371f9u, 0x22330b29u, 0x1f532299u, 0xad73fe89u, 0x9013d739u, 0xd7b3ade9u, 0xead38459u, - 0x68831388u, 0x55e33a38u, 0x124340e8u, 0x2f236958u, 0x9d03b548u, 0xa0639cf8u, 0xe7c3e628u, 0xdaa3cf98u, - 0x3813cfcbu, 0x0573e67bu, 0x42d39cabu, 0x7fb3b51bu, 0xcd93690bu, 0xf0f340bbu, 0xb7533a6bu, 0x8a3313dbu, - 0x0863840au, 0x3503adbau, 0x72a3d76au, 0x4fc3fedau, 0xfde322cau, 0xc0830b7au, 0x872371aau, 0xba43581au, - 0x9932774du, 0xa4525efdu, 0xe3f2242du, 0xde920d9du, 0x6cb2d18du, 0x51d2f83du, 0x167282edu, 0x2b12ab5du, - 0xa9423c8cu, 0x9422153cu, 0xd3826fecu, 0xeee2465cu, 0x5cc29a4cu, 0x61a2b3fcu, 0x2602c92cu, 0x1b62e09cu, - 0xf9d2e0cfu, 0xc4b2c97fu, 0x8312b3afu, 0xbe729a1fu, 0x0c52460fu, 0x31326fbfu, 0x7692156fu, 0x4bf23cdfu, - 0xc9a2ab0eu, 0xf4c282beu, 0xb362f86eu, 0x8e02d1deu, 0x3c220dceu, 0x0142247eu, 0x46e25eaeu, 0x7b82771eu, - 0xb1e6b092u, 0x8c869922u, 0xcb26e3f2u, 0xf646ca42u, 0x44661652u, 0x79063fe2u, 0x3ea64532u, 0x03c66c82u, - 0x8196fb53u, 0xbcf6d2e3u, 0xfb56a833u, 0xc6368183u, 0x74165d93u, 0x49767423u, 0x0ed60ef3u, 0x33b62743u, - 0xd1062710u, 0xec660ea0u, 0xabc67470u, 0x96a65dc0u, 0x248681d0u, 0x19e6a860u, 0x5e46d2b0u, 0x6326fb00u, - 0xe1766cd1u, 0xdc164561u, 0x9bb63fb1u, 0xa6d61601u, 0x14f6ca11u, 0x2996e3a1u, 0x6e369971u, 0x5356b0c1u, - 0x70279f96u, 0x4d47b626u, 0x0ae7ccf6u, 0x3787e546u, 0x85a73956u, 0xb8c710e6u, 0xff676a36u, 0xc2074386u, - 0x4057d457u, 0x7d37fde7u, 0x3a978737u, 0x07f7ae87u, 0xb5d77297u, 0x88b75b27u, 0xcf1721f7u, 0xf2770847u, - 0x10c70814u, 0x2da721a4u, 0x6a075b74u, 0x576772c4u, 0xe547aed4u, 0xd8278764u, 0x9f87fdb4u, 0xa2e7d404u, - 0x20b743d5u, 0x1dd76a65u, 0x5a7710b5u, 0x67173905u, 0xd537e515u, 0xe857cca5u, 0xaff7b675u, 0x92979fc5u, - 0xe915e8dbu, 0xd475c16bu, 0x93d5bbbbu, 0xaeb5920bu, 0x1c954e1bu, 0x21f567abu, 0x66551d7bu, 0x5b3534cbu, - 0xd965a31au, 0xe4058aaau, 0xa3a5f07au, 0x9ec5d9cau, 0x2ce505dau, 0x11852c6au, 0x562556bau, 0x6b457f0au, - 0x89f57f59u, 0xb49556e9u, 0xf3352c39u, 0xce550589u, 0x7c75d999u, 0x4115f029u, 0x06b58af9u, 0x3bd5a349u, - 0xb9853498u, 0x84e51d28u, 0xc34567f8u, 0xfe254e48u, 0x4c059258u, 0x7165bbe8u, 0x36c5c138u, 0x0ba5e888u, - 0x28d4c7dfu, 0x15b4ee6fu, 0x521494bfu, 0x6f74bd0fu, 0xdd54611fu, 0xe03448afu, 0xa794327fu, 0x9af41bcfu, - 0x18a48c1eu, 0x25c4a5aeu, 0x6264df7eu, 0x5f04f6ceu, 0xed242adeu, 0xd044036eu, 0x97e479beu, 0xaa84500eu, - 0x4834505du, 0x755479edu, 0x32f4033du, 0x0f942a8du, 0xbdb4f69du, 0x80d4df2du, 0xc774a5fdu, 0xfa148c4du, - 0x78441b9cu, 0x4524322cu, 0x028448fcu, 0x3fe4614cu, 0x8dc4bd5cu, 0xb0a494ecu, 0xf704ee3cu, 0xca64c78cu -}; - -static const unsigned lodepng_crc32_table5[256] = { - 0x00000000u, 0xcb5cd3a5u, 0x4dc8a10bu, 0x869472aeu, 0x9b914216u, 0x50cd91b3u, 0xd659e31du, 0x1d0530b8u, - 0xec53826du, 0x270f51c8u, 0xa19b2366u, 0x6ac7f0c3u, 0x77c2c07bu, 0xbc9e13deu, 0x3a0a6170u, 0xf156b2d5u, - 0x03d6029bu, 0xc88ad13eu, 0x4e1ea390u, 0x85427035u, 0x9847408du, 0x531b9328u, 0xd58fe186u, 0x1ed33223u, - 0xef8580f6u, 0x24d95353u, 0xa24d21fdu, 0x6911f258u, 0x7414c2e0u, 0xbf481145u, 0x39dc63ebu, 0xf280b04eu, - 0x07ac0536u, 0xccf0d693u, 0x4a64a43du, 0x81387798u, 0x9c3d4720u, 0x57619485u, 0xd1f5e62bu, 0x1aa9358eu, - 0xebff875bu, 0x20a354feu, 0xa6372650u, 0x6d6bf5f5u, 0x706ec54du, 0xbb3216e8u, 0x3da66446u, 0xf6fab7e3u, - 0x047a07adu, 0xcf26d408u, 0x49b2a6a6u, 0x82ee7503u, 0x9feb45bbu, 0x54b7961eu, 0xd223e4b0u, 0x197f3715u, - 0xe82985c0u, 0x23755665u, 0xa5e124cbu, 0x6ebdf76eu, 0x73b8c7d6u, 0xb8e41473u, 0x3e7066ddu, 0xf52cb578u, - 0x0f580a6cu, 0xc404d9c9u, 0x4290ab67u, 0x89cc78c2u, 0x94c9487au, 0x5f959bdfu, 0xd901e971u, 0x125d3ad4u, - 0xe30b8801u, 0x28575ba4u, 0xaec3290au, 0x659ffaafu, 0x789aca17u, 0xb3c619b2u, 0x35526b1cu, 0xfe0eb8b9u, - 0x0c8e08f7u, 0xc7d2db52u, 0x4146a9fcu, 0x8a1a7a59u, 0x971f4ae1u, 0x5c439944u, 0xdad7ebeau, 0x118b384fu, - 0xe0dd8a9au, 0x2b81593fu, 0xad152b91u, 0x6649f834u, 0x7b4cc88cu, 0xb0101b29u, 0x36846987u, 0xfdd8ba22u, - 0x08f40f5au, 0xc3a8dcffu, 0x453cae51u, 0x8e607df4u, 0x93654d4cu, 0x58399ee9u, 0xdeadec47u, 0x15f13fe2u, - 0xe4a78d37u, 0x2ffb5e92u, 0xa96f2c3cu, 0x6233ff99u, 0x7f36cf21u, 0xb46a1c84u, 0x32fe6e2au, 0xf9a2bd8fu, - 0x0b220dc1u, 0xc07ede64u, 0x46eaaccau, 0x8db67f6fu, 0x90b34fd7u, 0x5bef9c72u, 0xdd7beedcu, 0x16273d79u, - 0xe7718facu, 0x2c2d5c09u, 0xaab92ea7u, 0x61e5fd02u, 0x7ce0cdbau, 0xb7bc1e1fu, 0x31286cb1u, 0xfa74bf14u, - 0x1eb014d8u, 0xd5ecc77du, 0x5378b5d3u, 0x98246676u, 0x852156ceu, 0x4e7d856bu, 0xc8e9f7c5u, 0x03b52460u, - 0xf2e396b5u, 0x39bf4510u, 0xbf2b37beu, 0x7477e41bu, 0x6972d4a3u, 0xa22e0706u, 0x24ba75a8u, 0xefe6a60du, - 0x1d661643u, 0xd63ac5e6u, 0x50aeb748u, 0x9bf264edu, 0x86f75455u, 0x4dab87f0u, 0xcb3ff55eu, 0x006326fbu, - 0xf135942eu, 0x3a69478bu, 0xbcfd3525u, 0x77a1e680u, 0x6aa4d638u, 0xa1f8059du, 0x276c7733u, 0xec30a496u, - 0x191c11eeu, 0xd240c24bu, 0x54d4b0e5u, 0x9f886340u, 0x828d53f8u, 0x49d1805du, 0xcf45f2f3u, 0x04192156u, - 0xf54f9383u, 0x3e134026u, 0xb8873288u, 0x73dbe12du, 0x6eded195u, 0xa5820230u, 0x2316709eu, 0xe84aa33bu, - 0x1aca1375u, 0xd196c0d0u, 0x5702b27eu, 0x9c5e61dbu, 0x815b5163u, 0x4a0782c6u, 0xcc93f068u, 0x07cf23cdu, - 0xf6999118u, 0x3dc542bdu, 0xbb513013u, 0x700de3b6u, 0x6d08d30eu, 0xa65400abu, 0x20c07205u, 0xeb9ca1a0u, - 0x11e81eb4u, 0xdab4cd11u, 0x5c20bfbfu, 0x977c6c1au, 0x8a795ca2u, 0x41258f07u, 0xc7b1fda9u, 0x0ced2e0cu, - 0xfdbb9cd9u, 0x36e74f7cu, 0xb0733dd2u, 0x7b2fee77u, 0x662adecfu, 0xad760d6au, 0x2be27fc4u, 0xe0beac61u, - 0x123e1c2fu, 0xd962cf8au, 0x5ff6bd24u, 0x94aa6e81u, 0x89af5e39u, 0x42f38d9cu, 0xc467ff32u, 0x0f3b2c97u, - 0xfe6d9e42u, 0x35314de7u, 0xb3a53f49u, 0x78f9ececu, 0x65fcdc54u, 0xaea00ff1u, 0x28347d5fu, 0xe368aefau, - 0x16441b82u, 0xdd18c827u, 0x5b8cba89u, 0x90d0692cu, 0x8dd55994u, 0x46898a31u, 0xc01df89fu, 0x0b412b3au, - 0xfa1799efu, 0x314b4a4au, 0xb7df38e4u, 0x7c83eb41u, 0x6186dbf9u, 0xaada085cu, 0x2c4e7af2u, 0xe712a957u, - 0x15921919u, 0xdececabcu, 0x585ab812u, 0x93066bb7u, 0x8e035b0fu, 0x455f88aau, 0xc3cbfa04u, 0x089729a1u, - 0xf9c19b74u, 0x329d48d1u, 0xb4093a7fu, 0x7f55e9dau, 0x6250d962u, 0xa90c0ac7u, 0x2f987869u, 0xe4c4abccu -}; - -static const unsigned lodepng_crc32_table6[256] = { - 0x00000000u, 0xa6770bb4u, 0x979f1129u, 0x31e81a9du, 0xf44f2413u, 0x52382fa7u, 0x63d0353au, 0xc5a73e8eu, - 0x33ef4e67u, 0x959845d3u, 0xa4705f4eu, 0x020754fau, 0xc7a06a74u, 0x61d761c0u, 0x503f7b5du, 0xf64870e9u, - 0x67de9cceu, 0xc1a9977au, 0xf0418de7u, 0x56368653u, 0x9391b8ddu, 0x35e6b369u, 0x040ea9f4u, 0xa279a240u, - 0x5431d2a9u, 0xf246d91du, 0xc3aec380u, 0x65d9c834u, 0xa07ef6bau, 0x0609fd0eu, 0x37e1e793u, 0x9196ec27u, - 0xcfbd399cu, 0x69ca3228u, 0x582228b5u, 0xfe552301u, 0x3bf21d8fu, 0x9d85163bu, 0xac6d0ca6u, 0x0a1a0712u, - 0xfc5277fbu, 0x5a257c4fu, 0x6bcd66d2u, 0xcdba6d66u, 0x081d53e8u, 0xae6a585cu, 0x9f8242c1u, 0x39f54975u, - 0xa863a552u, 0x0e14aee6u, 0x3ffcb47bu, 0x998bbfcfu, 0x5c2c8141u, 0xfa5b8af5u, 0xcbb39068u, 0x6dc49bdcu, - 0x9b8ceb35u, 0x3dfbe081u, 0x0c13fa1cu, 0xaa64f1a8u, 0x6fc3cf26u, 0xc9b4c492u, 0xf85cde0fu, 0x5e2bd5bbu, - 0x440b7579u, 0xe27c7ecdu, 0xd3946450u, 0x75e36fe4u, 0xb044516au, 0x16335adeu, 0x27db4043u, 0x81ac4bf7u, - 0x77e43b1eu, 0xd19330aau, 0xe07b2a37u, 0x460c2183u, 0x83ab1f0du, 0x25dc14b9u, 0x14340e24u, 0xb2430590u, - 0x23d5e9b7u, 0x85a2e203u, 0xb44af89eu, 0x123df32au, 0xd79acda4u, 0x71edc610u, 0x4005dc8du, 0xe672d739u, - 0x103aa7d0u, 0xb64dac64u, 0x87a5b6f9u, 0x21d2bd4du, 0xe47583c3u, 0x42028877u, 0x73ea92eau, 0xd59d995eu, - 0x8bb64ce5u, 0x2dc14751u, 0x1c295dccu, 0xba5e5678u, 0x7ff968f6u, 0xd98e6342u, 0xe86679dfu, 0x4e11726bu, - 0xb8590282u, 0x1e2e0936u, 0x2fc613abu, 0x89b1181fu, 0x4c162691u, 0xea612d25u, 0xdb8937b8u, 0x7dfe3c0cu, - 0xec68d02bu, 0x4a1fdb9fu, 0x7bf7c102u, 0xdd80cab6u, 0x1827f438u, 0xbe50ff8cu, 0x8fb8e511u, 0x29cfeea5u, - 0xdf879e4cu, 0x79f095f8u, 0x48188f65u, 0xee6f84d1u, 0x2bc8ba5fu, 0x8dbfb1ebu, 0xbc57ab76u, 0x1a20a0c2u, - 0x8816eaf2u, 0x2e61e146u, 0x1f89fbdbu, 0xb9fef06fu, 0x7c59cee1u, 0xda2ec555u, 0xebc6dfc8u, 0x4db1d47cu, - 0xbbf9a495u, 0x1d8eaf21u, 0x2c66b5bcu, 0x8a11be08u, 0x4fb68086u, 0xe9c18b32u, 0xd82991afu, 0x7e5e9a1bu, - 0xefc8763cu, 0x49bf7d88u, 0x78576715u, 0xde206ca1u, 0x1b87522fu, 0xbdf0599bu, 0x8c184306u, 0x2a6f48b2u, - 0xdc27385bu, 0x7a5033efu, 0x4bb82972u, 0xedcf22c6u, 0x28681c48u, 0x8e1f17fcu, 0xbff70d61u, 0x198006d5u, - 0x47abd36eu, 0xe1dcd8dau, 0xd034c247u, 0x7643c9f3u, 0xb3e4f77du, 0x1593fcc9u, 0x247be654u, 0x820cede0u, - 0x74449d09u, 0xd23396bdu, 0xe3db8c20u, 0x45ac8794u, 0x800bb91au, 0x267cb2aeu, 0x1794a833u, 0xb1e3a387u, - 0x20754fa0u, 0x86024414u, 0xb7ea5e89u, 0x119d553du, 0xd43a6bb3u, 0x724d6007u, 0x43a57a9au, 0xe5d2712eu, - 0x139a01c7u, 0xb5ed0a73u, 0x840510eeu, 0x22721b5au, 0xe7d525d4u, 0x41a22e60u, 0x704a34fdu, 0xd63d3f49u, - 0xcc1d9f8bu, 0x6a6a943fu, 0x5b828ea2u, 0xfdf58516u, 0x3852bb98u, 0x9e25b02cu, 0xafcdaab1u, 0x09baa105u, - 0xfff2d1ecu, 0x5985da58u, 0x686dc0c5u, 0xce1acb71u, 0x0bbdf5ffu, 0xadcafe4bu, 0x9c22e4d6u, 0x3a55ef62u, - 0xabc30345u, 0x0db408f1u, 0x3c5c126cu, 0x9a2b19d8u, 0x5f8c2756u, 0xf9fb2ce2u, 0xc813367fu, 0x6e643dcbu, - 0x982c4d22u, 0x3e5b4696u, 0x0fb35c0bu, 0xa9c457bfu, 0x6c636931u, 0xca146285u, 0xfbfc7818u, 0x5d8b73acu, - 0x03a0a617u, 0xa5d7ada3u, 0x943fb73eu, 0x3248bc8au, 0xf7ef8204u, 0x519889b0u, 0x6070932du, 0xc6079899u, - 0x304fe870u, 0x9638e3c4u, 0xa7d0f959u, 0x01a7f2edu, 0xc400cc63u, 0x6277c7d7u, 0x539fdd4au, 0xf5e8d6feu, - 0x647e3ad9u, 0xc209316du, 0xf3e12bf0u, 0x55962044u, 0x90311ecau, 0x3646157eu, 0x07ae0fe3u, 0xa1d90457u, - 0x579174beu, 0xf1e67f0au, 0xc00e6597u, 0x66796e23u, 0xa3de50adu, 0x05a95b19u, 0x34414184u, 0x92364a30u -}; - -static const unsigned lodepng_crc32_table7[256] = { - 0x00000000u, 0xccaa009eu, 0x4225077du, 0x8e8f07e3u, 0x844a0efau, 0x48e00e64u, 0xc66f0987u, 0x0ac50919u, - 0xd3e51bb5u, 0x1f4f1b2bu, 0x91c01cc8u, 0x5d6a1c56u, 0x57af154fu, 0x9b0515d1u, 0x158a1232u, 0xd92012acu, - 0x7cbb312bu, 0xb01131b5u, 0x3e9e3656u, 0xf23436c8u, 0xf8f13fd1u, 0x345b3f4fu, 0xbad438acu, 0x767e3832u, - 0xaf5e2a9eu, 0x63f42a00u, 0xed7b2de3u, 0x21d12d7du, 0x2b142464u, 0xe7be24fau, 0x69312319u, 0xa59b2387u, - 0xf9766256u, 0x35dc62c8u, 0xbb53652bu, 0x77f965b5u, 0x7d3c6cacu, 0xb1966c32u, 0x3f196bd1u, 0xf3b36b4fu, - 0x2a9379e3u, 0xe639797du, 0x68b67e9eu, 0xa41c7e00u, 0xaed97719u, 0x62737787u, 0xecfc7064u, 0x205670fau, - 0x85cd537du, 0x496753e3u, 0xc7e85400u, 0x0b42549eu, 0x01875d87u, 0xcd2d5d19u, 0x43a25afau, 0x8f085a64u, - 0x562848c8u, 0x9a824856u, 0x140d4fb5u, 0xd8a74f2bu, 0xd2624632u, 0x1ec846acu, 0x9047414fu, 0x5ced41d1u, - 0x299dc2edu, 0xe537c273u, 0x6bb8c590u, 0xa712c50eu, 0xadd7cc17u, 0x617dcc89u, 0xeff2cb6au, 0x2358cbf4u, - 0xfa78d958u, 0x36d2d9c6u, 0xb85dde25u, 0x74f7debbu, 0x7e32d7a2u, 0xb298d73cu, 0x3c17d0dfu, 0xf0bdd041u, - 0x5526f3c6u, 0x998cf358u, 0x1703f4bbu, 0xdba9f425u, 0xd16cfd3cu, 0x1dc6fda2u, 0x9349fa41u, 0x5fe3fadfu, - 0x86c3e873u, 0x4a69e8edu, 0xc4e6ef0eu, 0x084cef90u, 0x0289e689u, 0xce23e617u, 0x40ace1f4u, 0x8c06e16au, - 0xd0eba0bbu, 0x1c41a025u, 0x92cea7c6u, 0x5e64a758u, 0x54a1ae41u, 0x980baedfu, 0x1684a93cu, 0xda2ea9a2u, - 0x030ebb0eu, 0xcfa4bb90u, 0x412bbc73u, 0x8d81bcedu, 0x8744b5f4u, 0x4beeb56au, 0xc561b289u, 0x09cbb217u, - 0xac509190u, 0x60fa910eu, 0xee7596edu, 0x22df9673u, 0x281a9f6au, 0xe4b09ff4u, 0x6a3f9817u, 0xa6959889u, - 0x7fb58a25u, 0xb31f8abbu, 0x3d908d58u, 0xf13a8dc6u, 0xfbff84dfu, 0x37558441u, 0xb9da83a2u, 0x7570833cu, - 0x533b85dau, 0x9f918544u, 0x111e82a7u, 0xddb48239u, 0xd7718b20u, 0x1bdb8bbeu, 0x95548c5du, 0x59fe8cc3u, - 0x80de9e6fu, 0x4c749ef1u, 0xc2fb9912u, 0x0e51998cu, 0x04949095u, 0xc83e900bu, 0x46b197e8u, 0x8a1b9776u, - 0x2f80b4f1u, 0xe32ab46fu, 0x6da5b38cu, 0xa10fb312u, 0xabcaba0bu, 0x6760ba95u, 0xe9efbd76u, 0x2545bde8u, - 0xfc65af44u, 0x30cfafdau, 0xbe40a839u, 0x72eaa8a7u, 0x782fa1beu, 0xb485a120u, 0x3a0aa6c3u, 0xf6a0a65du, - 0xaa4de78cu, 0x66e7e712u, 0xe868e0f1u, 0x24c2e06fu, 0x2e07e976u, 0xe2ade9e8u, 0x6c22ee0bu, 0xa088ee95u, - 0x79a8fc39u, 0xb502fca7u, 0x3b8dfb44u, 0xf727fbdau, 0xfde2f2c3u, 0x3148f25du, 0xbfc7f5beu, 0x736df520u, - 0xd6f6d6a7u, 0x1a5cd639u, 0x94d3d1dau, 0x5879d144u, 0x52bcd85du, 0x9e16d8c3u, 0x1099df20u, 0xdc33dfbeu, - 0x0513cd12u, 0xc9b9cd8cu, 0x4736ca6fu, 0x8b9ccaf1u, 0x8159c3e8u, 0x4df3c376u, 0xc37cc495u, 0x0fd6c40bu, - 0x7aa64737u, 0xb60c47a9u, 0x3883404au, 0xf42940d4u, 0xfeec49cdu, 0x32464953u, 0xbcc94eb0u, 0x70634e2eu, - 0xa9435c82u, 0x65e95c1cu, 0xeb665bffu, 0x27cc5b61u, 0x2d095278u, 0xe1a352e6u, 0x6f2c5505u, 0xa386559bu, - 0x061d761cu, 0xcab77682u, 0x44387161u, 0x889271ffu, 0x825778e6u, 0x4efd7878u, 0xc0727f9bu, 0x0cd87f05u, - 0xd5f86da9u, 0x19526d37u, 0x97dd6ad4u, 0x5b776a4au, 0x51b26353u, 0x9d1863cdu, 0x1397642eu, 0xdf3d64b0u, - 0x83d02561u, 0x4f7a25ffu, 0xc1f5221cu, 0x0d5f2282u, 0x079a2b9bu, 0xcb302b05u, 0x45bf2ce6u, 0x89152c78u, - 0x50353ed4u, 0x9c9f3e4au, 0x121039a9u, 0xdeba3937u, 0xd47f302eu, 0x18d530b0u, 0x965a3753u, 0x5af037cdu, - 0xff6b144au, 0x33c114d4u, 0xbd4e1337u, 0x71e413a9u, 0x7b211ab0u, 0xb78b1a2eu, 0x39041dcdu, 0xf5ae1d53u, - 0x2c8e0fffu, 0xe0240f61u, 0x6eab0882u, 0xa201081cu, 0xa8c40105u, 0x646e019bu, 0xeae10678u, 0x264b06e6u -}; - -/* Computes the cyclic redundancy check as used by PNG chunks*/ -unsigned lodepng_crc32(const unsigned char* data, size_t length) { - /*Using the Slicing by Eight algorithm*/ - unsigned r = 0xffffffffu; - while(length >= 8) { - r = lodepng_crc32_table7[(data[0] ^ (r & 0xffu))] ^ - lodepng_crc32_table6[(data[1] ^ ((r >> 8) & 0xffu))] ^ - lodepng_crc32_table5[(data[2] ^ ((r >> 16) & 0xffu))] ^ - lodepng_crc32_table4[(data[3] ^ ((r >> 24) & 0xffu))] ^ - lodepng_crc32_table3[data[4]] ^ - lodepng_crc32_table2[data[5]] ^ - lodepng_crc32_table1[data[6]] ^ - lodepng_crc32_table0[data[7]]; - data += 8; - length -= 8; - } - while(length--) { - r = lodepng_crc32_table0[(r ^ *data++) & 0xffu] ^ (r >> 8); - } - return r ^ 0xffffffffu; -} -#else /* LODEPNG_COMPILE_CRC */ -/*in this case, the function is only declared here, and must be defined externally -so that it will be linked in. - -Example implementation that uses a much smaller lookup table for memory constrained cases: - -unsigned lodepng_crc32(const unsigned char* data, size_t length) { - unsigned r = 0xffffffffu; - static const unsigned table[16] = { - 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, - 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c - }; - while(length--) { - r = table[(r ^ *data) & 0xf] ^ (r >> 4); - r = table[(r ^ (*data >> 4)) & 0xf] ^ (r >> 4); - data++; - } - return r ^ 0xffffffffu; -} -*/ -unsigned lodepng_crc32(const unsigned char* data, size_t length); -#endif /* LODEPNG_COMPILE_CRC */ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Reading and writing PNG color channel bits / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/* The color channel bits of less-than-8-bit pixels are read with the MSB of bytes first, -so LodePNGBitWriter and LodePNGBitReader can't be used for those. */ - -static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) { - unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); - ++(*bitpointer); - return result; -} - -/* TODO: make this faster */ -static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) { - unsigned result = 0; - size_t i; - for(i = 0 ; i < nbits; ++i) { - result <<= 1u; - result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream); - } - return result; -} - -static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) { - /*the current bit in bitstream may be 0 or 1 for this to work*/ - if(bit == 0) bitstream[(*bitpointer) >> 3u] &= (unsigned char)(~(1u << (7u - ((*bitpointer) & 7u)))); - else bitstream[(*bitpointer) >> 3u] |= (1u << (7u - ((*bitpointer) & 7u))); - ++(*bitpointer); -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG chunks / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -unsigned lodepng_chunk_length(const unsigned char* chunk) { - return lodepng_read32bitInt(chunk); -} - -void lodepng_chunk_type(char type[5], const unsigned char* chunk) { - unsigned i; - for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i]; - type[4] = 0; /*null termination char*/ -} - -unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type) { - if(lodepng_strlen(type) != 4) return 0; - return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]); -} - -unsigned char lodepng_chunk_ancillary(const unsigned char* chunk) { - return((chunk[4] & 32) != 0); -} - -unsigned char lodepng_chunk_private(const unsigned char* chunk) { - return((chunk[6] & 32) != 0); -} - -unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk) { - return((chunk[7] & 32) != 0); -} - -unsigned char* lodepng_chunk_data(unsigned char* chunk) { - return &chunk[8]; -} - -const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk) { - return &chunk[8]; -} - -unsigned lodepng_chunk_check_crc(const unsigned char* chunk) { - unsigned length = lodepng_chunk_length(chunk); - unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]); - /*the CRC is taken of the data and the 4 chunk type letters, not the length*/ - unsigned checksum = lodepng_crc32(&chunk[4], length + 4); - if(CRC != checksum) return 1; - else return 0; -} - -void lodepng_chunk_generate_crc(unsigned char* chunk) { - unsigned length = lodepng_chunk_length(chunk); - unsigned CRC = lodepng_crc32(&chunk[4], length + 4); - lodepng_set32bitInt(chunk + 8 + length, CRC); -} - -unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end) { - size_t available_size = (size_t)(end - chunk); - if(chunk >= end || available_size < 12) return end; /*too small to contain a chunk*/ - if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 - && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { - /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ - return chunk + 8; - } else { - size_t total_chunk_length; - if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end; - if(total_chunk_length > available_size) return end; /*outside of range*/ - return chunk + total_chunk_length; - } -} - -const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end) { - size_t available_size = (size_t)(end - chunk); - if(chunk >= end || available_size < 12) return end; /*too small to contain a chunk*/ - if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 - && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { - /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ - return chunk + 8; - } else { - size_t total_chunk_length; - if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end; - if(total_chunk_length > available_size) return end; /*outside of range*/ - return chunk + total_chunk_length; - } -} - -unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]) { - for(;;) { - if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */ - if(lodepng_chunk_type_equals(chunk, type)) return chunk; - chunk = lodepng_chunk_next(chunk, end); - } -} - -const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) { - for(;;) { - if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */ - if(lodepng_chunk_type_equals(chunk, type)) return chunk; - chunk = lodepng_chunk_next_const(chunk, end); - } -} - -unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk) { - unsigned i; - size_t total_chunk_length, new_length; - unsigned char *chunk_start, *new_buffer; - - if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return 77; - if(lodepng_addofl(*outsize, total_chunk_length, &new_length)) return 77; - - new_buffer = (unsigned char*)lodepng_realloc(*out, new_length); - if(!new_buffer) return 83; /*alloc fail*/ - (*out) = new_buffer; - (*outsize) = new_length; - chunk_start = &(*out)[new_length - total_chunk_length]; - - for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i]; - - return 0; -} - -/*Sets length and name and allocates the space for data and crc but does not -set data or crc yet. Returns the start of the chunk in chunk. The start of -the data is at chunk + 8. To finalize chunk, add the data, then use -lodepng_chunk_generate_crc */ -static unsigned lodepng_chunk_init(unsigned char** chunk, - ucvector* out, - unsigned length, const char* type) { - size_t new_length = out->size; - if(lodepng_addofl(new_length, length, &new_length)) return 77; - if(lodepng_addofl(new_length, 12, &new_length)) return 77; - if(!ucvector_resize(out, new_length)) return 83; /*alloc fail*/ - *chunk = out->data + new_length - length - 12u; - - /*1: length*/ - lodepng_set32bitInt(*chunk, length); - - /*2: chunk name (4 letters)*/ - lodepng_memcpy(*chunk + 4, type, 4); - - return 0; -} - -/* like lodepng_chunk_create but with custom allocsize */ -static unsigned lodepng_chunk_createv(ucvector* out, - unsigned length, const char* type, const unsigned char* data) { - unsigned char* chunk; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, length, type)); - - /*3: the data*/ - lodepng_memcpy(chunk + 8, data, length); - - /*4: CRC (of the chunkname characters and the data)*/ - lodepng_chunk_generate_crc(chunk); - - return 0; -} - -unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, - unsigned length, const char* type, const unsigned char* data) { - ucvector v = ucvector_init(*out, *outsize); - unsigned error = lodepng_chunk_createv(&v, length, type, data); - *out = v.data; - *outsize = v.size; - return error; -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Color types, channels, bits / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*checks if the colortype is valid and the bitdepth bd is allowed for this colortype. -Return value is a LodePNG error code.*/ -static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) { - switch(colortype) { - case LCT_GREY: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; - case LCT_RGB: if(!( bd == 8 || bd == 16)) return 37; break; - case LCT_PALETTE: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; - case LCT_GREY_ALPHA: if(!( bd == 8 || bd == 16)) return 37; break; - case LCT_RGBA: if(!( bd == 8 || bd == 16)) return 37; break; - case LCT_MAX_OCTET_VALUE: return 31; /* invalid color type */ - default: return 31; /* invalid color type */ - } - return 0; /*allowed color type / bits combination*/ -} - -static unsigned getNumColorChannels(LodePNGColorType colortype) { - switch(colortype) { - case LCT_GREY: return 1; - case LCT_RGB: return 3; - case LCT_PALETTE: return 1; - case LCT_GREY_ALPHA: return 2; - case LCT_RGBA: return 4; - case LCT_MAX_OCTET_VALUE: return 0; /* invalid color type */ - default: return 0; /*invalid color type*/ - } -} - -static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) { - /*bits per pixel is amount of channels * bits per channel*/ - return getNumColorChannels(colortype) * bitdepth; -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -void lodepng_color_mode_init(LodePNGColorMode* info) { - info->key_defined = 0; - info->key_r = info->key_g = info->key_b = 0; - info->colortype = LCT_RGBA; - info->bitdepth = 8; - info->palette = 0; - info->palettesize = 0; -} - -/*allocates palette memory if needed, and initializes all colors to black*/ -static void lodepng_color_mode_alloc_palette(LodePNGColorMode* info) { - size_t i; - /*if the palette is already allocated, it will have size 1024 so no reallocation needed in that case*/ - /*the palette must have room for up to 256 colors with 4 bytes each.*/ - if(!info->palette) info->palette = (unsigned char*)lodepng_malloc(1024); - if(!info->palette) return; /*alloc fail*/ - for(i = 0; i != 256; ++i) { - /*Initialize all unused colors with black, the value used for invalid palette indices. - This is an error according to the PNG spec, but common PNG decoders make it black instead. - That makes color conversion slightly faster due to no error handling needed.*/ - info->palette[i * 4 + 0] = 0; - info->palette[i * 4 + 1] = 0; - info->palette[i * 4 + 2] = 0; - info->palette[i * 4 + 3] = 255; - } -} - -void lodepng_color_mode_cleanup(LodePNGColorMode* info) { - lodepng_palette_clear(info); -} - -unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source) { - lodepng_color_mode_cleanup(dest); - lodepng_memcpy(dest, source, sizeof(LodePNGColorMode)); - if(source->palette) { - dest->palette = (unsigned char*)lodepng_malloc(1024); - if(!dest->palette && source->palettesize) return 83; /*alloc fail*/ - lodepng_memcpy(dest->palette, source->palette, source->palettesize * 4); - } - return 0; -} - -LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth) { - LodePNGColorMode result; - lodepng_color_mode_init(&result); - result.colortype = colortype; - result.bitdepth = bitdepth; - return result; -} - -static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b) { - size_t i; - if(a->colortype != b->colortype) return 0; - if(a->bitdepth != b->bitdepth) return 0; - if(a->key_defined != b->key_defined) return 0; - if(a->key_defined) { - if(a->key_r != b->key_r) return 0; - if(a->key_g != b->key_g) return 0; - if(a->key_b != b->key_b) return 0; - } - if(a->palettesize != b->palettesize) return 0; - for(i = 0; i != a->palettesize * 4; ++i) { - if(a->palette[i] != b->palette[i]) return 0; - } - return 1; -} - -void lodepng_palette_clear(LodePNGColorMode* info) { - if(info->palette) lodepng_free(info->palette); - info->palette = 0; - info->palettesize = 0; -} - -unsigned lodepng_palette_add(LodePNGColorMode* info, - unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - if(!info->palette) /*allocate palette if empty*/ { - lodepng_color_mode_alloc_palette(info); - if(!info->palette) return 83; /*alloc fail*/ - } - if(info->palettesize >= 256) { - return 108; /*too many palette values*/ - } - info->palette[4 * info->palettesize + 0] = r; - info->palette[4 * info->palettesize + 1] = g; - info->palette[4 * info->palettesize + 2] = b; - info->palette[4 * info->palettesize + 3] = a; - ++info->palettesize; - return 0; -} - -/*calculate bits per pixel out of colortype and bitdepth*/ -unsigned lodepng_get_bpp(const LodePNGColorMode* info) { - return lodepng_get_bpp_lct(info->colortype, info->bitdepth); -} - -unsigned lodepng_get_channels(const LodePNGColorMode* info) { - return getNumColorChannels(info->colortype); -} - -unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info) { - return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA; -} - -unsigned lodepng_is_alpha_type(const LodePNGColorMode* info) { - return (info->colortype & 4) != 0; /*4 or 6*/ -} - -unsigned lodepng_is_palette_type(const LodePNGColorMode* info) { - return info->colortype == LCT_PALETTE; -} - -unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info) { - size_t i; - for(i = 0; i != info->palettesize; ++i) { - if(info->palette[i * 4 + 3] < 255) return 1; - } - return 0; -} - -unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) { - return info->key_defined - || lodepng_is_alpha_type(info) - || lodepng_has_palette_alpha(info); -} - -static size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) { - size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); - size_t n = (size_t)w * (size_t)h; - return ((n / 8u) * bpp) + ((n & 7u) * bpp + 7u) / 8u; -} - -size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) { - return lodepng_get_raw_size_lct(w, h, color->colortype, color->bitdepth); -} - - -#ifdef LODEPNG_COMPILE_PNG - -/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer, -and in addition has one extra byte per line: the filter byte. So this gives a larger -result than lodepng_get_raw_size. Set h to 1 to get the size of 1 row including filter byte. */ -static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, unsigned bpp) { - /* + 1 for the filter byte, and possibly plus padding bits per line. */ - /* Ignoring casts, the expression is equal to (w * bpp + 7) / 8 + 1, but avoids overflow of w * bpp */ - size_t line = ((size_t)(w / 8u) * bpp) + 1u + ((w & 7u) * bpp + 7u) / 8u; - return (size_t)h * line; -} - -#ifdef LODEPNG_COMPILE_DECODER -/*Safely checks whether size_t overflow can be caused due to amount of pixels. -This check is overcautious rather than precise. If this check indicates no overflow, -you can safely compute in a size_t (but not an unsigned): --(size_t)w * (size_t)h * 8 --amount of bytes in IDAT (including filter, padding and Adam7 bytes) --amount of bytes in raw color model -Returns 1 if overflow possible, 0 if not. -*/ -static int lodepng_pixel_overflow(unsigned w, unsigned h, - const LodePNGColorMode* pngcolor, const LodePNGColorMode* rawcolor) { - size_t bpp = LODEPNG_MAX(lodepng_get_bpp(pngcolor), lodepng_get_bpp(rawcolor)); - size_t numpixels, total; - size_t line; /* bytes per line in worst case */ - - if(lodepng_mulofl((size_t)w, (size_t)h, &numpixels)) return 1; - if(lodepng_mulofl(numpixels, 8, &total)) return 1; /* bit pointer with 8-bit color, or 8 bytes per channel color */ - - /* Bytes per scanline with the expression "(w / 8u) * bpp) + ((w & 7u) * bpp + 7u) / 8u" */ - if(lodepng_mulofl((size_t)(w / 8u), bpp, &line)) return 1; - if(lodepng_addofl(line, ((w & 7u) * bpp + 7u) / 8u, &line)) return 1; - - if(lodepng_addofl(line, 5, &line)) return 1; /* 5 bytes overhead per line: 1 filterbyte, 4 for Adam7 worst case */ - if(lodepng_mulofl(line, h, &total)) return 1; /* Total bytes in worst case */ - - return 0; /* no overflow */ -} -#endif /*LODEPNG_COMPILE_DECODER*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - -static void LodePNGUnknownChunks_init(LodePNGInfo* info) { - unsigned i; - for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0; - for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0; -} - -static void LodePNGUnknownChunks_cleanup(LodePNGInfo* info) { - unsigned i; - for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]); -} - -static unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src) { - unsigned i; - - LodePNGUnknownChunks_cleanup(dest); - - for(i = 0; i != 3; ++i) { - size_t j; - dest->unknown_chunks_size[i] = src->unknown_chunks_size[i]; - dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]); - if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/ - for(j = 0; j < src->unknown_chunks_size[i]; ++j) { - dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j]; - } - } - - return 0; -} - -/******************************************************************************/ - -static void LodePNGText_init(LodePNGInfo* info) { - info->text_num = 0; - info->text_keys = NULL; - info->text_strings = NULL; -} - -static void LodePNGText_cleanup(LodePNGInfo* info) { - size_t i; - for(i = 0; i != info->text_num; ++i) { - string_cleanup(&info->text_keys[i]); - string_cleanup(&info->text_strings[i]); - } - lodepng_free(info->text_keys); - lodepng_free(info->text_strings); -} - -static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) { - size_t i = 0; - dest->text_keys = NULL; - dest->text_strings = NULL; - dest->text_num = 0; - for(i = 0; i != source->text_num; ++i) { - CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i])); - } - return 0; -} - -static unsigned lodepng_add_text_sized(LodePNGInfo* info, const char* key, const char* str, size_t size) { - char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1))); - char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1))); - - if(new_keys) info->text_keys = new_keys; - if(new_strings) info->text_strings = new_strings; - - if(!new_keys || !new_strings) return 83; /*alloc fail*/ - - ++info->text_num; - info->text_keys[info->text_num - 1] = alloc_string(key); - info->text_strings[info->text_num - 1] = alloc_string_sized(str, size); - if(!info->text_keys[info->text_num - 1] || !info->text_strings[info->text_num - 1]) return 83; /*alloc fail*/ - - return 0; -} - -unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str) { - return lodepng_add_text_sized(info, key, str, lodepng_strlen(str)); -} - -void lodepng_clear_text(LodePNGInfo* info) { - LodePNGText_cleanup(info); -} - -/******************************************************************************/ - -static void LodePNGIText_init(LodePNGInfo* info) { - info->itext_num = 0; - info->itext_keys = NULL; - info->itext_langtags = NULL; - info->itext_transkeys = NULL; - info->itext_strings = NULL; -} - -static void LodePNGIText_cleanup(LodePNGInfo* info) { - size_t i; - for(i = 0; i != info->itext_num; ++i) { - string_cleanup(&info->itext_keys[i]); - string_cleanup(&info->itext_langtags[i]); - string_cleanup(&info->itext_transkeys[i]); - string_cleanup(&info->itext_strings[i]); - } - lodepng_free(info->itext_keys); - lodepng_free(info->itext_langtags); - lodepng_free(info->itext_transkeys); - lodepng_free(info->itext_strings); -} - -static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) { - size_t i = 0; - dest->itext_keys = NULL; - dest->itext_langtags = NULL; - dest->itext_transkeys = NULL; - dest->itext_strings = NULL; - dest->itext_num = 0; - for(i = 0; i != source->itext_num; ++i) { - CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i], - source->itext_transkeys[i], source->itext_strings[i])); - } - return 0; -} - -void lodepng_clear_itext(LodePNGInfo* info) { - LodePNGIText_cleanup(info); -} - -static unsigned lodepng_add_itext_sized(LodePNGInfo* info, const char* key, const char* langtag, - const char* transkey, const char* str, size_t size) { - char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1))); - char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1))); - char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1))); - char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1))); - - if(new_keys) info->itext_keys = new_keys; - if(new_langtags) info->itext_langtags = new_langtags; - if(new_transkeys) info->itext_transkeys = new_transkeys; - if(new_strings) info->itext_strings = new_strings; - - if(!new_keys || !new_langtags || !new_transkeys || !new_strings) return 83; /*alloc fail*/ - - ++info->itext_num; - - info->itext_keys[info->itext_num - 1] = alloc_string(key); - info->itext_langtags[info->itext_num - 1] = alloc_string(langtag); - info->itext_transkeys[info->itext_num - 1] = alloc_string(transkey); - info->itext_strings[info->itext_num - 1] = alloc_string_sized(str, size); - - return 0; -} - -unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, - const char* transkey, const char* str) { - return lodepng_add_itext_sized(info, key, langtag, transkey, str, lodepng_strlen(str)); -} - -/* same as set but does not delete */ -static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) { - if(profile_size == 0) return 100; /*invalid ICC profile size*/ - - info->iccp_name = alloc_string(name); - info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size); - - if(!info->iccp_name || !info->iccp_profile) return 83; /*alloc fail*/ - - lodepng_memcpy(info->iccp_profile, profile, profile_size); - info->iccp_profile_size = profile_size; - - return 0; /*ok*/ -} - -unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) { - if(info->iccp_name) lodepng_clear_icc(info); - info->iccp_defined = 1; - - return lodepng_assign_icc(info, name, profile, profile_size); -} - -void lodepng_clear_icc(LodePNGInfo* info) { - string_cleanup(&info->iccp_name); - lodepng_free(info->iccp_profile); - info->iccp_profile = NULL; - info->iccp_profile_size = 0; - info->iccp_defined = 0; -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -void lodepng_info_init(LodePNGInfo* info) { - lodepng_color_mode_init(&info->color); - info->interlace_method = 0; - info->compression_method = 0; - info->filter_method = 0; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - info->background_defined = 0; - info->background_r = info->background_g = info->background_b = 0; - - LodePNGText_init(info); - LodePNGIText_init(info); - - info->time_defined = 0; - info->phys_defined = 0; - - info->gama_defined = 0; - info->chrm_defined = 0; - info->srgb_defined = 0; - info->iccp_defined = 0; - info->iccp_name = NULL; - info->iccp_profile = NULL; - - info->sbit_defined = 0; - info->sbit_r = info->sbit_g = info->sbit_b = info->sbit_a = 0; - - LodePNGUnknownChunks_init(info); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} - -void lodepng_info_cleanup(LodePNGInfo* info) { - lodepng_color_mode_cleanup(&info->color); -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - LodePNGText_cleanup(info); - LodePNGIText_cleanup(info); - - lodepng_clear_icc(info); - - LodePNGUnknownChunks_cleanup(info); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} - -unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) { - lodepng_info_cleanup(dest); - lodepng_memcpy(dest, source, sizeof(LodePNGInfo)); - lodepng_color_mode_init(&dest->color); - CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color)); - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - CERROR_TRY_RETURN(LodePNGText_copy(dest, source)); - CERROR_TRY_RETURN(LodePNGIText_copy(dest, source)); - if(source->iccp_defined) { - CERROR_TRY_RETURN(lodepng_assign_icc(dest, source->iccp_name, source->iccp_profile, source->iccp_profile_size)); - } - - LodePNGUnknownChunks_init(dest); - CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source)); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - return 0; -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/ -static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) { - unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/ - /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/ - unsigned p = index & m; - in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/ - in = in << (bits * (m - p)); - if(p == 0) out[index * bits / 8u] = in; - else out[index * bits / 8u] |= in; -} - -typedef struct ColorTree ColorTree; - -/* -One node of a color tree -This is the data structure used to count the number of unique colors and to get a palette -index for a color. It's like an octree, but because the alpha channel is used too, each -node has 16 instead of 8 children. -*/ -struct ColorTree { - ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/ - int index; /*the payload. Only has a meaningful value if this is in the last level*/ -}; - -static void color_tree_init(ColorTree* tree) { - lodepng_memset(tree->children, 0, 16 * sizeof(*tree->children)); - tree->index = -1; -} - -static void color_tree_cleanup(ColorTree* tree) { - int i; - for(i = 0; i != 16; ++i) { - if(tree->children[i]) { - color_tree_cleanup(tree->children[i]); - lodepng_free(tree->children[i]); - } - } -} - -/*returns -1 if color not present, its index otherwise*/ -static int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - int bit = 0; - for(bit = 0; bit < 8; ++bit) { - int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); - if(!tree->children[i]) return -1; - else tree = tree->children[i]; - } - return tree ? tree->index : -1; -} - -#ifdef LODEPNG_COMPILE_ENCODER -static int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - return color_tree_get(tree, r, g, b, a) >= 0; -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -/*color is not allowed to already exist. -Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist") -Returns error code, or 0 if ok*/ -static unsigned color_tree_add(ColorTree* tree, - unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) { - int bit; - for(bit = 0; bit < 8; ++bit) { - int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); - if(!tree->children[i]) { - tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree)); - if(!tree->children[i]) return 83; /*alloc fail*/ - color_tree_init(tree->children[i]); - } - tree = tree->children[i]; - } - tree->index = (int)index; - return 0; -} - -/*put a pixel, given its RGBA color, into image of any color type*/ -static unsigned rgba8ToPixel(unsigned char* out, size_t i, - const LodePNGColorMode* mode, ColorTree* tree /*for palette*/, - unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - if(mode->colortype == LCT_GREY) { - unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ - if(mode->bitdepth == 8) out[i] = gray; - else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = gray; - else { - /*take the most significant bits of gray*/ - gray = ((unsigned)gray >> (8u - mode->bitdepth)) & ((1u << mode->bitdepth) - 1u); - addColorBits(out, i, mode->bitdepth, gray); - } - } else if(mode->colortype == LCT_RGB) { - if(mode->bitdepth == 8) { - out[i * 3 + 0] = r; - out[i * 3 + 1] = g; - out[i * 3 + 2] = b; - } else { - out[i * 6 + 0] = out[i * 6 + 1] = r; - out[i * 6 + 2] = out[i * 6 + 3] = g; - out[i * 6 + 4] = out[i * 6 + 5] = b; - } - } else if(mode->colortype == LCT_PALETTE) { - int index = color_tree_get(tree, r, g, b, a); - if(index < 0) return 82; /*color not in palette*/ - if(mode->bitdepth == 8) out[i] = index; - else addColorBits(out, i, mode->bitdepth, (unsigned)index); - } else if(mode->colortype == LCT_GREY_ALPHA) { - unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ - if(mode->bitdepth == 8) { - out[i * 2 + 0] = gray; - out[i * 2 + 1] = a; - } else if(mode->bitdepth == 16) { - out[i * 4 + 0] = out[i * 4 + 1] = gray; - out[i * 4 + 2] = out[i * 4 + 3] = a; - } - } else if(mode->colortype == LCT_RGBA) { - if(mode->bitdepth == 8) { - out[i * 4 + 0] = r; - out[i * 4 + 1] = g; - out[i * 4 + 2] = b; - out[i * 4 + 3] = a; - } else { - out[i * 8 + 0] = out[i * 8 + 1] = r; - out[i * 8 + 2] = out[i * 8 + 3] = g; - out[i * 8 + 4] = out[i * 8 + 5] = b; - out[i * 8 + 6] = out[i * 8 + 7] = a; - } - } - - return 0; /*no error*/ -} - -/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/ -static void rgba16ToPixel(unsigned char* out, size_t i, - const LodePNGColorMode* mode, - unsigned short r, unsigned short g, unsigned short b, unsigned short a) { - if(mode->colortype == LCT_GREY) { - unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/ - out[i * 2 + 0] = (gray >> 8) & 255; - out[i * 2 + 1] = gray & 255; - } else if(mode->colortype == LCT_RGB) { - out[i * 6 + 0] = (r >> 8) & 255; - out[i * 6 + 1] = r & 255; - out[i * 6 + 2] = (g >> 8) & 255; - out[i * 6 + 3] = g & 255; - out[i * 6 + 4] = (b >> 8) & 255; - out[i * 6 + 5] = b & 255; - } else if(mode->colortype == LCT_GREY_ALPHA) { - unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/ - out[i * 4 + 0] = (gray >> 8) & 255; - out[i * 4 + 1] = gray & 255; - out[i * 4 + 2] = (a >> 8) & 255; - out[i * 4 + 3] = a & 255; - } else if(mode->colortype == LCT_RGBA) { - out[i * 8 + 0] = (r >> 8) & 255; - out[i * 8 + 1] = r & 255; - out[i * 8 + 2] = (g >> 8) & 255; - out[i * 8 + 3] = g & 255; - out[i * 8 + 4] = (b >> 8) & 255; - out[i * 8 + 5] = b & 255; - out[i * 8 + 6] = (a >> 8) & 255; - out[i * 8 + 7] = a & 255; - } -} - -/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/ -static void getPixelColorRGBA8(unsigned char* r, unsigned char* g, - unsigned char* b, unsigned char* a, - const unsigned char* in, size_t i, - const LodePNGColorMode* mode) { - if(mode->colortype == LCT_GREY) { - if(mode->bitdepth == 8) { - *r = *g = *b = in[i]; - if(mode->key_defined && *r == mode->key_r) *a = 0; - else *a = 255; - } else if(mode->bitdepth == 16) { - *r = *g = *b = in[i * 2 + 0]; - if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; - else *a = 255; - } else { - unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ - size_t j = i * mode->bitdepth; - unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); - *r = *g = *b = (value * 255) / highest; - if(mode->key_defined && value == mode->key_r) *a = 0; - else *a = 255; - } - } else if(mode->colortype == LCT_RGB) { - if(mode->bitdepth == 8) { - *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2]; - if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0; - else *a = 255; - } else { - *r = in[i * 6 + 0]; - *g = in[i * 6 + 2]; - *b = in[i * 6 + 4]; - if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r - && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g - && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; - else *a = 255; - } - } else if(mode->colortype == LCT_PALETTE) { - unsigned index; - if(mode->bitdepth == 8) index = in[i]; - else { - size_t j = i * mode->bitdepth; - index = readBitsFromReversedStream(&j, in, mode->bitdepth); - } - /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ - *r = mode->palette[index * 4 + 0]; - *g = mode->palette[index * 4 + 1]; - *b = mode->palette[index * 4 + 2]; - *a = mode->palette[index * 4 + 3]; - } else if(mode->colortype == LCT_GREY_ALPHA) { - if(mode->bitdepth == 8) { - *r = *g = *b = in[i * 2 + 0]; - *a = in[i * 2 + 1]; - } else { - *r = *g = *b = in[i * 4 + 0]; - *a = in[i * 4 + 2]; - } - } else if(mode->colortype == LCT_RGBA) { - if(mode->bitdepth == 8) { - *r = in[i * 4 + 0]; - *g = in[i * 4 + 1]; - *b = in[i * 4 + 2]; - *a = in[i * 4 + 3]; - } else { - *r = in[i * 8 + 0]; - *g = in[i * 8 + 2]; - *b = in[i * 8 + 4]; - *a = in[i * 8 + 6]; - } - } -} - -/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color -mode test cases, optimized to convert the colors much faster, when converting -to the common case of RGBA with 8 bit per channel. buffer must be RGBA with -enough memory.*/ -static void getPixelColorsRGBA8(unsigned char* LODEPNG_RESTRICT buffer, size_t numpixels, - const unsigned char* LODEPNG_RESTRICT in, - const LodePNGColorMode* mode) { - unsigned num_channels = 4; - size_t i; - if(mode->colortype == LCT_GREY) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i]; - buffer[3] = 255; - } - if(mode->key_defined) { - buffer -= numpixels * num_channels; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - if(buffer[0] == mode->key_r) buffer[3] = 0; - } - } - } else if(mode->bitdepth == 16) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 2]; - buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255; - } - } else { - unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ - size_t j = 0; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); - buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; - buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255; - } - } - } else if(mode->colortype == LCT_RGB) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - lodepng_memcpy(buffer, &in[i * 3], 3); - buffer[3] = 255; - } - if(mode->key_defined) { - buffer -= numpixels * num_channels; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - if(buffer[0] == mode->key_r && buffer[1]== mode->key_g && buffer[2] == mode->key_b) buffer[3] = 0; - } - } - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = in[i * 6 + 0]; - buffer[1] = in[i * 6 + 2]; - buffer[2] = in[i * 6 + 4]; - buffer[3] = mode->key_defined - && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r - && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g - && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255; - } - } - } else if(mode->colortype == LCT_PALETTE) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned index = in[i]; - /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ - lodepng_memcpy(buffer, &mode->palette[index * 4], 4); - } - } else { - size_t j = 0; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth); - /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ - lodepng_memcpy(buffer, &mode->palette[index * 4], 4); - } - } - } else if(mode->colortype == LCT_GREY_ALPHA) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; - buffer[3] = in[i * 2 + 1]; - } - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; - buffer[3] = in[i * 4 + 2]; - } - } - } else if(mode->colortype == LCT_RGBA) { - if(mode->bitdepth == 8) { - lodepng_memcpy(buffer, in, numpixels * 4); - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = in[i * 8 + 0]; - buffer[1] = in[i * 8 + 2]; - buffer[2] = in[i * 8 + 4]; - buffer[3] = in[i * 8 + 6]; - } - } - } -} - -/*Similar to getPixelColorsRGBA8, but with 3-channel RGB output.*/ -static void getPixelColorsRGB8(unsigned char* LODEPNG_RESTRICT buffer, size_t numpixels, - const unsigned char* LODEPNG_RESTRICT in, - const LodePNGColorMode* mode) { - const unsigned num_channels = 3; - size_t i; - if(mode->colortype == LCT_GREY) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i]; - } - } else if(mode->bitdepth == 16) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 2]; - } - } else { - unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ - size_t j = 0; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); - buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; - } - } - } else if(mode->colortype == LCT_RGB) { - if(mode->bitdepth == 8) { - lodepng_memcpy(buffer, in, numpixels * 3); - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = in[i * 6 + 0]; - buffer[1] = in[i * 6 + 2]; - buffer[2] = in[i * 6 + 4]; - } - } - } else if(mode->colortype == LCT_PALETTE) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned index = in[i]; - /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ - lodepng_memcpy(buffer, &mode->palette[index * 4], 3); - } - } else { - size_t j = 0; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth); - /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ - lodepng_memcpy(buffer, &mode->palette[index * 4], 3); - } - } - } else if(mode->colortype == LCT_GREY_ALPHA) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; - } - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; - } - } - } else if(mode->colortype == LCT_RGBA) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - lodepng_memcpy(buffer, &in[i * 4], 3); - } - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = in[i * 8 + 0]; - buffer[1] = in[i * 8 + 2]; - buffer[2] = in[i * 8 + 4]; - } - } - } -} - -/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with -given color type, but the given color type must be 16-bit itself.*/ -static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a, - const unsigned char* in, size_t i, const LodePNGColorMode* mode) { - if(mode->colortype == LCT_GREY) { - *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1]; - if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; - else *a = 65535; - } else if(mode->colortype == LCT_RGB) { - *r = 256u * in[i * 6 + 0] + in[i * 6 + 1]; - *g = 256u * in[i * 6 + 2] + in[i * 6 + 3]; - *b = 256u * in[i * 6 + 4] + in[i * 6 + 5]; - if(mode->key_defined - && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r - && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g - && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; - else *a = 65535; - } else if(mode->colortype == LCT_GREY_ALPHA) { - *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1]; - *a = 256u * in[i * 4 + 2] + in[i * 4 + 3]; - } else if(mode->colortype == LCT_RGBA) { - *r = 256u * in[i * 8 + 0] + in[i * 8 + 1]; - *g = 256u * in[i * 8 + 2] + in[i * 8 + 3]; - *b = 256u * in[i * 8 + 4] + in[i * 8 + 5]; - *a = 256u * in[i * 8 + 6] + in[i * 8 + 7]; - } -} - -unsigned lodepng_convert(unsigned char* out, const unsigned char* in, - const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, - unsigned w, unsigned h) { - size_t i; - ColorTree tree; - size_t numpixels = (size_t)w * (size_t)h; - unsigned error = 0; - - if(mode_in->colortype == LCT_PALETTE && !mode_in->palette) { - return 107; /* error: must provide palette if input mode is palette */ - } - - if(lodepng_color_mode_equal(mode_out, mode_in)) { - size_t numbytes = lodepng_get_raw_size(w, h, mode_in); - lodepng_memcpy(out, in, numbytes); - return 0; - } - - if(mode_out->colortype == LCT_PALETTE) { - size_t palettesize = mode_out->palettesize; - const unsigned char* palette = mode_out->palette; - size_t palsize = (size_t)1u << mode_out->bitdepth; - /*if the user specified output palette but did not give the values, assume - they want the values of the input color type (assuming that one is palette). - Note that we never create a new palette ourselves.*/ - if(palettesize == 0) { - palettesize = mode_in->palettesize; - palette = mode_in->palette; - /*if the input was also palette with same bitdepth, then the color types are also - equal, so copy literally. This to preserve the exact indices that were in the PNG - even in case there are duplicate colors in the palette.*/ - if(mode_in->colortype == LCT_PALETTE && mode_in->bitdepth == mode_out->bitdepth) { - size_t numbytes = lodepng_get_raw_size(w, h, mode_in); - lodepng_memcpy(out, in, numbytes); - return 0; - } - } - if(palettesize < palsize) palsize = palettesize; - color_tree_init(&tree); - for(i = 0; i != palsize; ++i) { - const unsigned char* p = &palette[i * 4]; - error = color_tree_add(&tree, p[0], p[1], p[2], p[3], (unsigned)i); - if(error) break; - } - } - - if(!error) { - if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16) { - for(i = 0; i != numpixels; ++i) { - unsigned short r = 0, g = 0, b = 0, a = 0; - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); - rgba16ToPixel(out, i, mode_out, r, g, b, a); - } - } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) { - getPixelColorsRGBA8(out, numpixels, in, mode_in); - } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) { - getPixelColorsRGB8(out, numpixels, in, mode_in); - } else { - unsigned char r = 0, g = 0, b = 0, a = 0; - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); - error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a); - if(error) break; - } - } - } - - if(mode_out->colortype == LCT_PALETTE) { - color_tree_cleanup(&tree); - } - - return error; -} - - -/* Converts a single rgb color without alpha from one type to another, color bits truncated to -their bitdepth. In case of single channel (gray or palette), only the r channel is used. Slow -function, do not use to process all pixels of an image. Alpha channel not supported on purpose: -this is for bKGD, supporting alpha may prevent it from finding a color in the palette, from the -specification it looks like bKGD should ignore the alpha values of the palette since it can use -any palette index but doesn't have an alpha channel. Idem with ignoring color key. */ -unsigned lodepng_convert_rgb( - unsigned* r_out, unsigned* g_out, unsigned* b_out, - unsigned r_in, unsigned g_in, unsigned b_in, - const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in) { - unsigned r = 0, g = 0, b = 0; - unsigned mul = 65535 / ((1u << mode_in->bitdepth) - 1u); /*65535, 21845, 4369, 257, 1*/ - unsigned shift = 16 - mode_out->bitdepth; - - if(mode_in->colortype == LCT_GREY || mode_in->colortype == LCT_GREY_ALPHA) { - r = g = b = r_in * mul; - } else if(mode_in->colortype == LCT_RGB || mode_in->colortype == LCT_RGBA) { - r = r_in * mul; - g = g_in * mul; - b = b_in * mul; - } else if(mode_in->colortype == LCT_PALETTE) { - if(r_in >= mode_in->palettesize) return 82; - r = mode_in->palette[r_in * 4 + 0] * 257u; - g = mode_in->palette[r_in * 4 + 1] * 257u; - b = mode_in->palette[r_in * 4 + 2] * 257u; - } else { - return 31; - } - - /* now convert to output format */ - if(mode_out->colortype == LCT_GREY || mode_out->colortype == LCT_GREY_ALPHA) { - *r_out = r >> shift ; - } else if(mode_out->colortype == LCT_RGB || mode_out->colortype == LCT_RGBA) { - *r_out = r >> shift ; - *g_out = g >> shift ; - *b_out = b >> shift ; - } else if(mode_out->colortype == LCT_PALETTE) { - unsigned i; - /* a 16-bit color cannot be in the palette */ - if((r >> 8) != (r & 255) || (g >> 8) != (g & 255) || (b >> 8) != (b & 255)) return 82; - for(i = 0; i < mode_out->palettesize; i++) { - unsigned j = i * 4; - if((r >> 8) == mode_out->palette[j + 0] && (g >> 8) == mode_out->palette[j + 1] && - (b >> 8) == mode_out->palette[j + 2]) { - *r_out = i; - return 0; - } - } - return 82; - } else { - return 31; - } - - return 0; -} - -#ifdef LODEPNG_COMPILE_ENCODER - -void lodepng_color_stats_init(LodePNGColorStats* stats) { - /*stats*/ - stats->colored = 0; - stats->key = 0; - stats->key_r = stats->key_g = stats->key_b = 0; - stats->alpha = 0; - stats->numcolors = 0; - stats->bits = 1; - stats->numpixels = 0; - /*settings*/ - stats->allow_palette = 1; - stats->allow_greyscale = 1; -} - -/*function used for debug purposes with C++*/ -/*void printColorStats(LodePNGColorStats* p) { - std::cout << "colored: " << (int)p->colored << ", "; - std::cout << "key: " << (int)p->key << ", "; - std::cout << "key_r: " << (int)p->key_r << ", "; - std::cout << "key_g: " << (int)p->key_g << ", "; - std::cout << "key_b: " << (int)p->key_b << ", "; - std::cout << "alpha: " << (int)p->alpha << ", "; - std::cout << "numcolors: " << (int)p->numcolors << ", "; - std::cout << "bits: " << (int)p->bits << std::endl; -}*/ - -/*Returns how many bits needed to represent given value (max 8 bit)*/ -static unsigned getValueRequiredBits(unsigned char value) { - if(value == 0 || value == 255) return 1; - /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/ - if(value % 17 == 0) return value % 85 == 0 ? 2 : 4; - return 8; -} - -/*stats must already have been inited. */ -unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, - const unsigned char* in, unsigned w, unsigned h, - const LodePNGColorMode* mode_in) { - size_t i; - ColorTree tree; - size_t numpixels = (size_t)w * (size_t)h; - unsigned error = 0; - - /* mark things as done already if it would be impossible to have a more expensive case */ - unsigned colored_done = lodepng_is_greyscale_type(mode_in) ? 1 : 0; - unsigned alpha_done = lodepng_can_have_alpha(mode_in) ? 0 : 1; - unsigned numcolors_done = 0; - unsigned bpp = lodepng_get_bpp(mode_in); - unsigned bits_done = (stats->bits == 1 && bpp == 1) ? 1 : 0; - unsigned sixteen = 0; /* whether the input image is 16 bit */ - unsigned maxnumcolors = 257; - if(bpp <= 8) maxnumcolors = LODEPNG_MIN(257, stats->numcolors + (1u << bpp)); - - stats->numpixels += numpixels; - - /*if palette not allowed, no need to compute numcolors*/ - if(!stats->allow_palette) numcolors_done = 1; - - color_tree_init(&tree); - - /*If the stats was already filled in from previous data, fill its palette in tree - and mark things as done already if we know they are the most expensive case already*/ - if(stats->alpha) alpha_done = 1; - if(stats->colored) colored_done = 1; - if(stats->bits == 16) numcolors_done = 1; - if(stats->bits >= bpp) bits_done = 1; - if(stats->numcolors >= maxnumcolors) numcolors_done = 1; - - if(!numcolors_done) { - for(i = 0; i < stats->numcolors; i++) { - const unsigned char* color = &stats->palette[i * 4]; - error = color_tree_add(&tree, color[0], color[1], color[2], color[3], i); - if(error) goto cleanup; - } - } - - /*Check if the 16-bit input is truly 16-bit*/ - if(mode_in->bitdepth == 16 && !sixteen) { - unsigned short r = 0, g = 0, b = 0, a = 0; - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); - if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) || - (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/ { - stats->bits = 16; - sixteen = 1; - bits_done = 1; - numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/ - break; - } - } - } - - if(sixteen) { - unsigned short r = 0, g = 0, b = 0, a = 0; - - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); - - if(!colored_done && (r != g || r != b)) { - stats->colored = 1; - colored_done = 1; - } - - if(!alpha_done) { - unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b); - if(a != 65535 && (a != 0 || (stats->key && !matchkey))) { - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - } else if(a == 0 && !stats->alpha && !stats->key) { - stats->key = 1; - stats->key_r = r; - stats->key_g = g; - stats->key_b = b; - } else if(a == 65535 && stats->key && matchkey) { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - } - } - if(alpha_done && numcolors_done && colored_done && bits_done) break; - } - - if(stats->key && !stats->alpha) { - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); - if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - } - } - } - } else /* < 16-bit */ { - unsigned char r = 0, g = 0, b = 0, a = 0; - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); - - if(!bits_done && stats->bits < 8) { - /*only r is checked, < 8 bits is only relevant for grayscale*/ - unsigned bits = getValueRequiredBits(r); - if(bits > stats->bits) stats->bits = bits; - } - bits_done = (stats->bits >= bpp); - - if(!colored_done && (r != g || r != b)) { - stats->colored = 1; - colored_done = 1; - if(stats->bits < 8) stats->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/ - } - - if(!alpha_done) { - unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b); - if(a != 255 && (a != 0 || (stats->key && !matchkey))) { - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } else if(a == 0 && !stats->alpha && !stats->key) { - stats->key = 1; - stats->key_r = r; - stats->key_g = g; - stats->key_b = b; - } else if(a == 255 && stats->key && matchkey) { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } - } - - if(!numcolors_done) { - if(!color_tree_has(&tree, r, g, b, a)) { - error = color_tree_add(&tree, r, g, b, a, stats->numcolors); - if(error) goto cleanup; - if(stats->numcolors < 256) { - unsigned char* p = stats->palette; - unsigned n = stats->numcolors; - p[n * 4 + 0] = r; - p[n * 4 + 1] = g; - p[n * 4 + 2] = b; - p[n * 4 + 3] = a; - } - ++stats->numcolors; - numcolors_done = stats->numcolors >= maxnumcolors; - } - } - - if(alpha_done && numcolors_done && colored_done && bits_done) break; - } - - if(stats->key && !stats->alpha) { - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); - if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } - } - } - - /*make the stats's key always 16-bit for consistency - repeat each byte twice*/ - stats->key_r += (stats->key_r << 8); - stats->key_g += (stats->key_g << 8); - stats->key_b += (stats->key_b << 8); - } - -cleanup: - color_tree_cleanup(&tree); - return error; -} - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -/*Adds a single color to the color stats. The stats must already have been inited. The color must be given as 16-bit -(with 2 bytes repeating for 8-bit and 65535 for opaque alpha channel). This function is expensive, do not call it for -all pixels of an image but only for a few additional values. */ -static unsigned lodepng_color_stats_add(LodePNGColorStats* stats, - unsigned r, unsigned g, unsigned b, unsigned a) { - unsigned error = 0; - unsigned char image[8]; - LodePNGColorMode mode; - lodepng_color_mode_init(&mode); - image[0] = r >> 8; image[1] = r; image[2] = g >> 8; image[3] = g; - image[4] = b >> 8; image[5] = b; image[6] = a >> 8; image[7] = a; - mode.bitdepth = 16; - mode.colortype = LCT_RGBA; - error = lodepng_compute_color_stats(stats, image, 1, 1, &mode); - lodepng_color_mode_cleanup(&mode); - return error; -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -/*Computes a minimal PNG color model that can contain all colors as indicated by the stats. -The stats should be computed with lodepng_compute_color_stats. -mode_in is raw color profile of the image the stats were computed on, to copy palette order from when relevant. -Minimal PNG color model means the color type and bit depth that gives smallest amount of bits in the output image, -e.g. gray if only grayscale pixels, palette if less than 256 colors, color key if only single transparent color, ... -This is used if auto_convert is enabled (it is by default). -*/ -static unsigned auto_choose_color(LodePNGColorMode* mode_out, - const LodePNGColorMode* mode_in, - const LodePNGColorStats* stats) { - unsigned error = 0; - unsigned palettebits; - size_t i, n; - size_t numpixels = stats->numpixels; - unsigned palette_ok, gray_ok; - - unsigned alpha = stats->alpha; - unsigned key = stats->key; - unsigned bits = stats->bits; - - mode_out->key_defined = 0; - - if(key && numpixels <= 16) { - alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ - key = 0; - if(bits < 8) bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } - - gray_ok = !stats->colored; - if(!stats->allow_greyscale) gray_ok = 0; - if(!gray_ok && bits < 8) bits = 8; - - n = stats->numcolors; - palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); - palette_ok = n <= 256 && bits <= 8 && n != 0; /*n==0 means likely numcolors wasn't computed*/ - if(numpixels < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ - if(gray_ok && !alpha && bits <= palettebits) palette_ok = 0; /*gray is less overhead*/ - if(!stats->allow_palette) palette_ok = 0; - - if(palette_ok) { - const unsigned char* p = stats->palette; - lodepng_palette_clear(mode_out); /*remove potential earlier palette*/ - for(i = 0; i != stats->numcolors; ++i) { - error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]); - if(error) break; - } - - mode_out->colortype = LCT_PALETTE; - mode_out->bitdepth = palettebits; - - if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize - && mode_in->bitdepth == mode_out->bitdepth) { - /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/ - lodepng_color_mode_cleanup(mode_out); /*clears palette, keeps the above set colortype and bitdepth fields as-is*/ - lodepng_color_mode_copy(mode_out, mode_in); - } - } else /*8-bit or 16-bit per channel*/ { - mode_out->bitdepth = bits; - mode_out->colortype = alpha ? (gray_ok ? LCT_GREY_ALPHA : LCT_RGBA) - : (gray_ok ? LCT_GREY : LCT_RGB); - if(key) { - unsigned mask = (1u << mode_out->bitdepth) - 1u; /*stats always uses 16-bit, mask converts it*/ - mode_out->key_r = stats->key_r & mask; - mode_out->key_g = stats->key_g & mask; - mode_out->key_b = stats->key_b & mask; - mode_out->key_defined = 1; - } - } - - return error; -} - -#endif /* #ifdef LODEPNG_COMPILE_ENCODER */ - -/*Paeth predictor, used by PNG filter type 4*/ -static unsigned char paethPredictor(unsigned char a, unsigned char b, unsigned char c) { - /* the subtractions of unsigned char cast it to a signed type. - With gcc, short is faster than int, with clang int is as fast (as of april 2023)*/ - short pa = (b - c) < 0 ? -(b - c) : (b - c); - short pb = (a - c) < 0 ? -(a - c) : (a - c); - /* writing it out like this compiles to something faster than introducing a temp variable*/ - short pc = (a + b - c - c) < 0 ? -(a + b - c - c) : (a + b - c - c); - /* return input value associated with smallest of pa, pb, pc (with certain priority if equal) */ - if(pb < pa) { a = b; pa = pb; } - return (pc < pa) ? c : a; -} - -/*shared values used by multiple Adam7 related functions*/ - -static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ -static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ -static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ -static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ - -/* -Outputs various dimensions and positions in the image related to the Adam7 reduced images. -passw: output containing the width of the 7 passes -passh: output containing the height of the 7 passes -filter_passstart: output containing the index of the start and end of each - reduced image with filter bytes -padded_passstart output containing the index of the start and end of each - reduced image when without filter bytes but with padded scanlines -passstart: output containing the index of the start and end of each reduced - image without padding between scanlines, but still padding between the images -w, h: width and height of non-interlaced image -bpp: bits per pixel -"padded" is only relevant if bpp is less than 8 and a scanline or image does not - end at a full byte -*/ -static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], - size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) { - /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/ - unsigned i; - - /*calculate width and height in pixels of each pass*/ - for(i = 0; i != 7; ++i) { - passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; - passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; - if(passw[i] == 0) passh[i] = 0; - if(passh[i] == 0) passw[i] = 0; - } - - filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; - for(i = 0; i != 7; ++i) { - /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ - filter_passstart[i + 1] = filter_passstart[i] - + ((passw[i] && passh[i]) ? passh[i] * (1u + (passw[i] * bpp + 7u) / 8u) : 0); - /*bits padded if needed to fill full byte at end of each scanline*/ - padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7u) / 8u); - /*only padded at end of reduced image*/ - passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7u) / 8u; - } -} - -#ifdef LODEPNG_COMPILE_DECODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG Decoder / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*read the information from the header and store it in the LodePNGInfo. return value is error*/ -unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state, - const unsigned char* in, size_t insize) { - unsigned width, height; - LodePNGInfo* info = &state->info_png; - if(insize == 0 || in == 0) { - CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/ - } - if(insize < 33) { - CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/ - } - - /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/ - /* TODO: remove this. One should use a new LodePNGState for new sessions */ - lodepng_info_cleanup(info); - lodepng_info_init(info); - - if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 - || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { - CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/ - } - if(lodepng_chunk_length(in + 8) != 13) { - CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/ - } - if(!lodepng_chunk_type_equals(in + 8, "IHDR")) { - CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/ - } - - /*read the values given in the header*/ - width = lodepng_read32bitInt(&in[16]); - height = lodepng_read32bitInt(&in[20]); - /*TODO: remove the undocumented feature that allows to give null pointers to width or height*/ - if(w) *w = width; - if(h) *h = height; - info->color.bitdepth = in[24]; - info->color.colortype = (LodePNGColorType)in[25]; - info->compression_method = in[26]; - info->filter_method = in[27]; - info->interlace_method = in[28]; - - /*errors returned only after the parsing so other values are still output*/ - - /*error: invalid image size*/ - if(width == 0 || height == 0) CERROR_RETURN_ERROR(state->error, 93); - /*error: invalid colortype or bitdepth combination*/ - state->error = checkColorValidity(info->color.colortype, info->color.bitdepth); - if(state->error) return state->error; - /*error: only compression method 0 is allowed in the specification*/ - if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32); - /*error: only filter method 0 is allowed in the specification*/ - if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33); - /*error: only interlace methods 0 and 1 exist in the specification*/ - if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34); - - if(!state->decoder.ignore_crc) { - unsigned CRC = lodepng_read32bitInt(&in[29]); - unsigned checksum = lodepng_crc32(&in[12], 17); - if(CRC != checksum) { - CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/ - } - } - - return state->error; -} - -static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, - size_t bytewidth, unsigned char filterType, size_t length) { - /* - For PNG filter method 0 - unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, - the filter works byte per byte (bytewidth = 1) - precon is the previous unfiltered scanline, recon the result, scanline the current one - the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead - recon and scanline MAY be the same memory address! precon must be disjoint. - */ - - size_t i; - switch(filterType) { - case 0: - for(i = 0; i != length; ++i) recon[i] = scanline[i]; - break; - case 1: { - size_t j = 0; - for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; - for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + recon[j]; - break; - } - case 2: - if(precon) { - for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i]; - } else { - for(i = 0; i != length; ++i) recon[i] = scanline[i]; - } - break; - case 3: - if(precon) { - size_t j = 0; - for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u); - /* Unroll independent paths of this predictor. A 6x and 8x version is also possible but that adds - too much code. Whether this speeds up anything depends on compiler and settings. */ - if(bytewidth >= 4) { - for(; i + 3 < length; i += 4, j += 4) { - unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3]; - unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3]; - unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3]; - recon[i + 0] = s0 + ((r0 + p0) >> 1u); - recon[i + 1] = s1 + ((r1 + p1) >> 1u); - recon[i + 2] = s2 + ((r2 + p2) >> 1u); - recon[i + 3] = s3 + ((r3 + p3) >> 1u); - } - } else if(bytewidth >= 3) { - for(; i + 2 < length; i += 3, j += 3) { - unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2]; - unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2]; - unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2]; - recon[i + 0] = s0 + ((r0 + p0) >> 1u); - recon[i + 1] = s1 + ((r1 + p1) >> 1u); - recon[i + 2] = s2 + ((r2 + p2) >> 1u); - } - } else if(bytewidth >= 2) { - for(; i + 1 < length; i += 2, j += 2) { - unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1]; - unsigned char r0 = recon[j + 0], r1 = recon[j + 1]; - unsigned char p0 = precon[i + 0], p1 = precon[i + 1]; - recon[i + 0] = s0 + ((r0 + p0) >> 1u); - recon[i + 1] = s1 + ((r1 + p1) >> 1u); - } - } - for(; i != length; ++i, ++j) recon[i] = scanline[i] + ((recon[j] + precon[i]) >> 1u); - } else { - size_t j = 0; - for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; - for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + (recon[j] >> 1u); - } - break; - case 4: - if(precon) { - /* Unroll independent paths of this predictor. Whether this speeds up - anything depends on compiler and settings. */ - if(bytewidth == 8) { - unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0; - unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0; - unsigned char a4, b4 = 0, c4, d4 = 0, a5, b5 = 0, c5, d5 = 0; - unsigned char a6, b6 = 0, c6, d6 = 0, a7, b7 = 0, c7, d7 = 0; - for(i = 0; i + 7 < length; i += 8) { - c0 = b0; c1 = b1; c2 = b2; c3 = b3; - c4 = b4; c5 = b5; c6 = b6; c7 = b7; - b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; b3 = precon[i + 3]; - b4 = precon[i + 4]; b5 = precon[i + 5]; b6 = precon[i + 6]; b7 = precon[i + 7]; - a0 = d0; a1 = d1; a2 = d2; a3 = d3; - a4 = d4; a5 = d5; a6 = d6; a7 = d7; - d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); - d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); - d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); - d3 = scanline[i + 3] + paethPredictor(a3, b3, c3); - d4 = scanline[i + 4] + paethPredictor(a4, b4, c4); - d5 = scanline[i + 5] + paethPredictor(a5, b5, c5); - d6 = scanline[i + 6] + paethPredictor(a6, b6, c6); - d7 = scanline[i + 7] + paethPredictor(a7, b7, c7); - recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; recon[i + 3] = d3; - recon[i + 4] = d4; recon[i + 5] = d5; recon[i + 6] = d6; recon[i + 7] = d7; - } - } else if(bytewidth == 6) { - unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0; - unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0; - unsigned char a4, b4 = 0, c4, d4 = 0, a5, b5 = 0, c5, d5 = 0; - for(i = 0; i + 5 < length; i += 6) { - c0 = b0; c1 = b1; c2 = b2; - c3 = b3; c4 = b4; c5 = b5; - b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; - b3 = precon[i + 3]; b4 = precon[i + 4]; b5 = precon[i + 5]; - a0 = d0; a1 = d1; a2 = d2; - a3 = d3; a4 = d4; a5 = d5; - d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); - d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); - d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); - d3 = scanline[i + 3] + paethPredictor(a3, b3, c3); - d4 = scanline[i + 4] + paethPredictor(a4, b4, c4); - d5 = scanline[i + 5] + paethPredictor(a5, b5, c5); - recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; - recon[i + 3] = d3; recon[i + 4] = d4; recon[i + 5] = d5; - } - } else if(bytewidth == 4) { - unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0; - unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0; - for(i = 0; i + 3 < length; i += 4) { - c0 = b0; c1 = b1; c2 = b2; c3 = b3; - b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; b3 = precon[i + 3]; - a0 = d0; a1 = d1; a2 = d2; a3 = d3; - d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); - d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); - d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); - d3 = scanline[i + 3] + paethPredictor(a3, b3, c3); - recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; recon[i + 3] = d3; - } - } else if(bytewidth == 3) { - unsigned char a0, b0 = 0, c0, d0 = 0; - unsigned char a1, b1 = 0, c1, d1 = 0; - unsigned char a2, b2 = 0, c2, d2 = 0; - for(i = 0; i + 2 < length; i += 3) { - c0 = b0; c1 = b1; c2 = b2; - b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; - a0 = d0; a1 = d1; a2 = d2; - d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); - d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); - d2 = scanline[i + 2] + paethPredictor(a2, b2, c2); - recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; - } - } else if(bytewidth == 2) { - unsigned char a0, b0 = 0, c0, d0 = 0; - unsigned char a1, b1 = 0, c1, d1 = 0; - for(i = 0; i + 1 < length; i += 2) { - c0 = b0; c1 = b1; - b0 = precon[i + 0]; - b1 = precon[i + 1]; - a0 = d0; a1 = d1; - d0 = scanline[i + 0] + paethPredictor(a0, b0, c0); - d1 = scanline[i + 1] + paethPredictor(a1, b1, c1); - recon[i + 0] = d0; - recon[i + 1] = d1; - } - } else if(bytewidth == 1) { - unsigned char a, b = 0, c, d = 0; - for(i = 0; i != length; ++i) { - c = b; - b = precon[i]; - a = d; - d = scanline[i] + paethPredictor(a, b, c); - recon[i] = d; - } - } else { - /* Normally not a possible case, but this would handle it correctly */ - for(i = 0; i != bytewidth; ++i) { - recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/ - } - } - /* finish any remaining bytes */ - for(; i != length; ++i) { - recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); - } - } else { - size_t j = 0; - for(i = 0; i != bytewidth; ++i) { - recon[i] = scanline[i]; - } - for(i = bytewidth; i != length; ++i, ++j) { - /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/ - recon[i] = (scanline[i] + recon[j]); - } - } - break; - default: return 36; /*error: invalid filter type given*/ - } - return 0; -} - -static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { - /* - For PNG filter method 0 - this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times) - out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline - w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel - in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes) - */ - - unsigned y; - unsigned char* prevline = 0; - - /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ - size_t bytewidth = (bpp + 7u) / 8u; - /*the width of a scanline in bytes, not including the filter type*/ - size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; - - for(y = 0; y < h; ++y) { - size_t outindex = linebytes * y; - size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ - unsigned char filterType = in[inindex]; - - CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes)); - - prevline = &out[outindex]; - } - - return 0; -} - -/* -in: Adam7 interlaced image, with no padding bits between scanlines, but between - reduced images so that each reduced image starts at a byte. -out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h -bpp: bits per pixel -out has the following size in bits: w * h * bpp. -in is possibly bigger due to padding bits between reduced images. -out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation -(because that's likely a little bit faster) -NOTE: comments about padding bits are only relevant if bpp < 8 -*/ -static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { - unsigned passw[7], passh[7]; - size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - if(bpp >= 8) { - for(i = 0; i != 7; ++i) { - unsigned x, y, b; - size_t bytewidth = bpp / 8u; - for(y = 0; y < passh[i]; ++y) - for(x = 0; x < passw[i]; ++x) { - size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth; - size_t pixeloutstart = ((ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * (size_t)w - + ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bytewidth; - for(b = 0; b < bytewidth; ++b) { - out[pixeloutstart + b] = in[pixelinstart + b]; - } - } - } - } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ { - for(i = 0; i != 7; ++i) { - unsigned x, y, b; - unsigned ilinebits = bpp * passw[i]; - unsigned olinebits = bpp * w; - size_t obp, ibp; /*bit pointers (for out and in buffer)*/ - for(y = 0; y < passh[i]; ++y) - for(x = 0; x < passw[i]; ++x) { - ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp); - obp = (ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bpp; - for(b = 0; b < bpp; ++b) { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - } - } - } -} - -static void removePaddingBits(unsigned char* out, const unsigned char* in, - size_t olinebits, size_t ilinebits, unsigned h) { - /* - After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need - to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers - for the Adam7 code, the color convert code and the output to the user. - in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must - have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits - also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7 - only useful if (ilinebits - olinebits) is a value in the range 1..7 - */ - unsigned y; - size_t diff = ilinebits - olinebits; - size_t ibp = 0, obp = 0; /*input and output bit pointers*/ - for(y = 0; y < h; ++y) { - size_t x; - for(x = 0; x < olinebits; ++x) { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - ibp += diff; - } -} - -/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from -the IDAT chunks (with filter index bytes and possible padding bits) -return value is error*/ -static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, - unsigned w, unsigned h, const LodePNGInfo* info_png) { - /* - This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. - Steps: - *) if no Adam7: 1) unfilter 2) remove padding bits (= possible extra bits per scanline if bpp < 8) - *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace - NOTE: the in buffer will be overwritten with intermediate data! - */ - unsigned bpp = lodepng_get_bpp(&info_png->color); - if(bpp == 0) return 31; /*error: invalid colortype*/ - - if(info_png->interlace_method == 0) { - if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) { - CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp)); - removePaddingBits(out, in, w * bpp, ((w * bpp + 7u) / 8u) * 8u, h); - } - /*we can immediately filter into the out buffer, no other steps needed*/ - else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp)); - } else /*interlace_method is 1 (Adam7)*/ { - unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - for(i = 0; i != 7; ++i) { - CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp)); - /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, - move bytes instead of bits or move not at all*/ - if(bpp < 8) { - /*remove padding bits in scanlines; after this there still may be padding - bits between the different reduced images: each reduced image still starts nicely at a byte*/ - removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, - ((passw[i] * bpp + 7u) / 8u) * 8u, passh[i]); - } - } - - Adam7_deinterlace(out, in, w, h, bpp); - } - - return 0; -} - -static unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) { - unsigned pos = 0, i; - color->palettesize = chunkLength / 3u; - if(color->palettesize == 0 || color->palettesize > 256) return 38; /*error: palette too small or big*/ - lodepng_color_mode_alloc_palette(color); - if(!color->palette && color->palettesize) { - color->palettesize = 0; - return 83; /*alloc fail*/ - } - - for(i = 0; i != color->palettesize; ++i) { - color->palette[4 * i + 0] = data[pos++]; /*R*/ - color->palette[4 * i + 1] = data[pos++]; /*G*/ - color->palette[4 * i + 2] = data[pos++]; /*B*/ - color->palette[4 * i + 3] = 255; /*alpha*/ - } - - return 0; /* OK */ -} - -static unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) { - unsigned i; - if(color->colortype == LCT_PALETTE) { - /*error: more alpha values given than there are palette entries*/ - if(chunkLength > color->palettesize) return 39; - - for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i]; - } else if(color->colortype == LCT_GREY) { - /*error: this chunk must be 2 bytes for grayscale image*/ - if(chunkLength != 2) return 30; - - color->key_defined = 1; - color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1]; - } else if(color->colortype == LCT_RGB) { - /*error: this chunk must be 6 bytes for RGB image*/ - if(chunkLength != 6) return 41; - - color->key_defined = 1; - color->key_r = 256u * data[0] + data[1]; - color->key_g = 256u * data[2] + data[3]; - color->key_b = 256u * data[4] + data[5]; - } - else return 42; /*error: tRNS chunk not allowed for other color models*/ - - return 0; /* OK */ -} - - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -/*background color chunk (bKGD)*/ -static unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(info->color.colortype == LCT_PALETTE) { - /*error: this chunk must be 1 byte for indexed color image*/ - if(chunkLength != 1) return 43; - - /*error: invalid palette index, or maybe this chunk appeared before PLTE*/ - if(data[0] >= info->color.palettesize) return 103; - - info->background_defined = 1; - info->background_r = info->background_g = info->background_b = data[0]; - } else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { - /*error: this chunk must be 2 bytes for grayscale image*/ - if(chunkLength != 2) return 44; - - /*the values are truncated to bitdepth in the PNG file*/ - info->background_defined = 1; - info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1]; - } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { - /*error: this chunk must be 6 bytes for grayscale image*/ - if(chunkLength != 6) return 45; - - /*the values are truncated to bitdepth in the PNG file*/ - info->background_defined = 1; - info->background_r = 256u * data[0] + data[1]; - info->background_g = 256u * data[2] + data[3]; - info->background_b = 256u * data[4] + data[5]; - } - - return 0; /* OK */ -} - -/*text chunk (tEXt)*/ -static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - unsigned error = 0; - char *key = 0, *str = 0; - - while(!error) /*not really a while loop, only used to break on error*/ { - unsigned length, string2_begin; - - length = 0; - while(length < chunkLength && data[length] != 0) ++length; - /*even though it's not allowed by the standard, no error is thrown if - there's no null termination char, if the text is empty*/ - if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ - - key = (char*)lodepng_malloc(length + 1); - if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(key, data, length); - key[length] = 0; - - string2_begin = length + 1; /*skip keyword null terminator*/ - - length = (unsigned)(chunkLength < string2_begin ? 0 : chunkLength - string2_begin); - str = (char*)lodepng_malloc(length + 1); - if(!str) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(str, data + string2_begin, length); - str[length] = 0; - - error = lodepng_add_text(info, key, str); - - break; - } - - lodepng_free(key); - lodepng_free(str); - - return error; -} - -/*compressed text chunk (zTXt)*/ -static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, - const unsigned char* data, size_t chunkLength) { - unsigned error = 0; - - /*copy the object to change parameters in it*/ - LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; - - unsigned length, string2_begin; - char *key = 0; - unsigned char* str = 0; - size_t size = 0; - - while(!error) /*not really a while loop, only used to break on error*/ { - for(length = 0; length < chunkLength && data[length] != 0; ++length) ; - if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ - if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ - - key = (char*)lodepng_malloc(length + 1); - if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(key, data, length); - key[length] = 0; - - if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ - - string2_begin = length + 2; - if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ - - length = (unsigned)chunkLength - string2_begin; - zlibsettings.max_output_size = decoder->max_text_size; - /*will fail if zlib error, e.g. if length is too small*/ - error = zlib_decompress(&str, &size, 0, &data[string2_begin], - length, &zlibsettings); - /*error: compressed text larger than decoder->max_text_size*/ - if(error && size > zlibsettings.max_output_size) error = 112; - if(error) break; - error = lodepng_add_text_sized(info, key, (char*)str, size); - break; - } - - lodepng_free(key); - lodepng_free(str); - - return error; -} - -/*international text chunk (iTXt)*/ -static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, - const unsigned char* data, size_t chunkLength) { - unsigned error = 0; - unsigned i; - - /*copy the object to change parameters in it*/ - LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; - - unsigned length, begin, compressed; - char *key = 0, *langtag = 0, *transkey = 0; - - while(!error) /*not really a while loop, only used to break on error*/ { - /*Quick check if the chunk length isn't too small. Even without check - it'd still fail with other error checks below if it's too short. This just gives a different error code.*/ - if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/ - - /*read the key*/ - for(length = 0; length < chunkLength && data[length] != 0; ++length) ; - if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/ - if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ - - key = (char*)lodepng_malloc(length + 1); - if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(key, data, length); - key[length] = 0; - - /*read the compression method*/ - compressed = data[length + 1]; - if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ - - /*even though it's not allowed by the standard, no error is thrown if - there's no null termination char, if the text is empty for the next 3 texts*/ - - /*read the langtag*/ - begin = length + 3; - length = 0; - for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; - - langtag = (char*)lodepng_malloc(length + 1); - if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(langtag, data + begin, length); - langtag[length] = 0; - - /*read the transkey*/ - begin += length + 1; - length = 0; - for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; - - transkey = (char*)lodepng_malloc(length + 1); - if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(transkey, data + begin, length); - transkey[length] = 0; - - /*read the actual text*/ - begin += length + 1; - - length = (unsigned)chunkLength < begin ? 0 : (unsigned)chunkLength - begin; - - if(compressed) { - unsigned char* str = 0; - size_t size = 0; - zlibsettings.max_output_size = decoder->max_text_size; - /*will fail if zlib error, e.g. if length is too small*/ - error = zlib_decompress(&str, &size, 0, &data[begin], - length, &zlibsettings); - /*error: compressed text larger than decoder->max_text_size*/ - if(error && size > zlibsettings.max_output_size) error = 112; - if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size); - lodepng_free(str); - } else { - error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)(data + begin), length); - } - - break; - } - - lodepng_free(key); - lodepng_free(langtag); - lodepng_free(transkey); - - return error; -} - -static unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(chunkLength != 7) return 73; /*invalid tIME chunk size*/ - - info->time_defined = 1; - info->time.year = 256u * data[0] + data[1]; - info->time.month = data[2]; - info->time.day = data[3]; - info->time.hour = data[4]; - info->time.minute = data[5]; - info->time.second = data[6]; - - return 0; /* OK */ -} - -static unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/ - - info->phys_defined = 1; - info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; - info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7]; - info->phys_unit = data[8]; - - return 0; /* OK */ -} - -static unsigned readChunk_gAMA(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(chunkLength != 4) return 96; /*invalid gAMA chunk size*/ - - info->gama_defined = 1; - info->gama_gamma = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; - - return 0; /* OK */ -} - -static unsigned readChunk_cHRM(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(chunkLength != 32) return 97; /*invalid cHRM chunk size*/ - - info->chrm_defined = 1; - info->chrm_white_x = 16777216u * data[ 0] + 65536u * data[ 1] + 256u * data[ 2] + data[ 3]; - info->chrm_white_y = 16777216u * data[ 4] + 65536u * data[ 5] + 256u * data[ 6] + data[ 7]; - info->chrm_red_x = 16777216u * data[ 8] + 65536u * data[ 9] + 256u * data[10] + data[11]; - info->chrm_red_y = 16777216u * data[12] + 65536u * data[13] + 256u * data[14] + data[15]; - info->chrm_green_x = 16777216u * data[16] + 65536u * data[17] + 256u * data[18] + data[19]; - info->chrm_green_y = 16777216u * data[20] + 65536u * data[21] + 256u * data[22] + data[23]; - info->chrm_blue_x = 16777216u * data[24] + 65536u * data[25] + 256u * data[26] + data[27]; - info->chrm_blue_y = 16777216u * data[28] + 65536u * data[29] + 256u * data[30] + data[31]; - - return 0; /* OK */ -} - -static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(chunkLength != 1) return 98; /*invalid sRGB chunk size (this one is never ignored)*/ - - info->srgb_defined = 1; - info->srgb_intent = data[0]; - - return 0; /* OK */ -} - -static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, - const unsigned char* data, size_t chunkLength) { - unsigned error = 0; - unsigned i; - size_t size = 0; - /*copy the object to change parameters in it*/ - LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; - - unsigned length, string2_begin; - - info->iccp_defined = 1; - if(info->iccp_name) lodepng_clear_icc(info); - - for(length = 0; length < chunkLength && data[length] != 0; ++length) ; - if(length + 2 >= chunkLength) return 75; /*no null termination, corrupt?*/ - if(length < 1 || length > 79) return 89; /*keyword too short or long*/ - - info->iccp_name = (char*)lodepng_malloc(length + 1); - if(!info->iccp_name) return 83; /*alloc fail*/ - - info->iccp_name[length] = 0; - for(i = 0; i != length; ++i) info->iccp_name[i] = (char)data[i]; - - if(data[length + 1] != 0) return 72; /*the 0 byte indicating compression must be 0*/ - - string2_begin = length + 2; - if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/ - - length = (unsigned)chunkLength - string2_begin; - zlibsettings.max_output_size = decoder->max_icc_size; - error = zlib_decompress(&info->iccp_profile, &size, 0, - &data[string2_begin], - length, &zlibsettings); - /*error: ICC profile larger than decoder->max_icc_size*/ - if(error && size > zlibsettings.max_output_size) error = 113; - info->iccp_profile_size = size; - if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/ - return error; -} - -/*significant bits chunk (sBIT)*/ -static unsigned readChunk_sBIT(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - unsigned bitdepth = (info->color.colortype == LCT_PALETTE) ? 8 : info->color.bitdepth; - if(info->color.colortype == LCT_GREY) { - /*error: this chunk must be 1 bytes for grayscale image*/ - if(chunkLength != 1) return 114; - if(data[0] == 0 || data[0] > bitdepth) return 115; - info->sbit_defined = 1; - info->sbit_r = info->sbit_g = info->sbit_b = data[0]; /*setting g and b is not required, but sensible*/ - } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_PALETTE) { - /*error: this chunk must be 3 bytes for RGB and palette image*/ - if(chunkLength != 3) return 114; - if(data[0] == 0 || data[1] == 0 || data[2] == 0) return 115; - if(data[0] > bitdepth || data[1] > bitdepth || data[2] > bitdepth) return 115; - info->sbit_defined = 1; - info->sbit_r = data[0]; - info->sbit_g = data[1]; - info->sbit_b = data[2]; - } else if(info->color.colortype == LCT_GREY_ALPHA) { - /*error: this chunk must be 2 byte for grayscale with alpha image*/ - if(chunkLength != 2) return 114; - if(data[0] == 0 || data[1] == 0) return 115; - if(data[0] > bitdepth || data[1] > bitdepth) return 115; - info->sbit_defined = 1; - info->sbit_r = info->sbit_g = info->sbit_b = data[0]; /*setting g and b is not required, but sensible*/ - info->sbit_a = data[1]; - } else if(info->color.colortype == LCT_RGBA) { - /*error: this chunk must be 4 bytes for grayscale image*/ - if(chunkLength != 4) return 114; - if(data[0] == 0 || data[1] == 0 || data[2] == 0 || data[3] == 0) return 115; - if(data[0] > bitdepth || data[1] > bitdepth || data[2] > bitdepth || data[3] > bitdepth) return 115; - info->sbit_defined = 1; - info->sbit_r = data[0]; - info->sbit_g = data[1]; - info->sbit_b = data[2]; - info->sbit_a = data[3]; - } - - return 0; /* OK */ -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, - const unsigned char* in, size_t insize) { - const unsigned char* chunk = in + pos; - unsigned chunkLength; - const unsigned char* data; - unsigned unhandled = 0; - unsigned error = 0; - - if(pos + 4 > insize) return 30; - chunkLength = lodepng_chunk_length(chunk); - if(chunkLength > 2147483647) return 63; - data = lodepng_chunk_data_const(chunk); - if(chunkLength + 12 > insize - pos) return 30; - - if(lodepng_chunk_type_equals(chunk, "PLTE")) { - error = readChunk_PLTE(&state->info_png.color, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "tRNS")) { - error = readChunk_tRNS(&state->info_png.color, data, chunkLength); -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - } else if(lodepng_chunk_type_equals(chunk, "bKGD")) { - error = readChunk_bKGD(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "tEXt")) { - error = readChunk_tEXt(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "zTXt")) { - error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "iTXt")) { - error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "tIME")) { - error = readChunk_tIME(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "pHYs")) { - error = readChunk_pHYs(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "gAMA")) { - error = readChunk_gAMA(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "cHRM")) { - error = readChunk_cHRM(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "sRGB")) { - error = readChunk_sRGB(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "iCCP")) { - error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "sBIT")) { - error = readChunk_sBIT(&state->info_png, data, chunkLength); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } else { - /* unhandled chunk is ok (is not an error) */ - unhandled = 1; - } - - if(!error && !unhandled && !state->decoder.ignore_crc) { - if(lodepng_chunk_check_crc(chunk)) return 57; /*invalid CRC*/ - } - - return error; -} - -/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ -static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize) { - unsigned char IEND = 0; - const unsigned char* chunk; /*points to beginning of next chunk*/ - unsigned char* idat; /*the data from idat chunks, zlib compressed*/ - size_t idatsize = 0; - unsigned char* scanlines = 0; - size_t scanlines_size = 0, expected_size = 0; - size_t outsize = 0; - - /*for unknown chunk order*/ - unsigned unknown = 0; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - - - /* safe output values in case error happens */ - *out = 0; - *w = *h = 0; - - state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ - if(state->error) return; - - if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) { - CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/ - } - - /*the input filesize is a safe upper bound for the sum of idat chunks size*/ - idat = (unsigned char*)lodepng_malloc(insize); - if(!idat) CERROR_RETURN(state->error, 83); /*alloc fail*/ - - chunk = &in[33]; /*first byte of the first chunk after the header*/ - - /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. - IDAT data is put at the start of the in buffer*/ - while(!IEND && !state->error) { - unsigned chunkLength; - const unsigned char* data; /*the data in the chunk*/ - size_t pos = (size_t)(chunk - in); - - /*error: next chunk out of bounds of the in buffer*/ - if(chunk < in || pos + 12 > insize) { - if(state->decoder.ignore_end) break; /*other errors may still happen though*/ - CERROR_BREAK(state->error, 30); - } - - /*length of the data of the chunk, excluding the 12 bytes for length, chunk type and CRC*/ - chunkLength = lodepng_chunk_length(chunk); - /*error: chunk length larger than the max PNG chunk size*/ - if(chunkLength > 2147483647) { - if(state->decoder.ignore_end) break; /*other errors may still happen though*/ - CERROR_BREAK(state->error, 63); - } - - if(pos + (size_t)chunkLength + 12 > insize || pos + (size_t)chunkLength + 12 < pos) { - CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk (or int overflow)*/ - } - - data = lodepng_chunk_data_const(chunk); - - unknown = 0; - - /*IDAT chunk, containing compressed image data*/ - if(lodepng_chunk_type_equals(chunk, "IDAT")) { - size_t newsize; - if(lodepng_addofl(idatsize, chunkLength, &newsize)) CERROR_BREAK(state->error, 95); - if(newsize > insize) CERROR_BREAK(state->error, 95); - lodepng_memcpy(idat + idatsize, data, chunkLength); - idatsize += chunkLength; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - critical_pos = 3; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } else if(lodepng_chunk_type_equals(chunk, "IEND")) { - /*IEND chunk*/ - IEND = 1; - } else if(lodepng_chunk_type_equals(chunk, "PLTE")) { - /*palette chunk (PLTE)*/ - state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength); - if(state->error) break; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - critical_pos = 2; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } else if(lodepng_chunk_type_equals(chunk, "tRNS")) { - /*palette transparency chunk (tRNS). Even though this one is an ancillary chunk , it is still compiled - in without 'LODEPNG_COMPILE_ANCILLARY_CHUNKS' because it contains essential color information that - affects the alpha channel of pixels. */ - state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength); - if(state->error) break; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*background color chunk (bKGD)*/ - } else if(lodepng_chunk_type_equals(chunk, "bKGD")) { - state->error = readChunk_bKGD(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "tEXt")) { - /*text chunk (tEXt)*/ - if(state->decoder.read_text_chunks) { - state->error = readChunk_tEXt(&state->info_png, data, chunkLength); - if(state->error) break; - } - } else if(lodepng_chunk_type_equals(chunk, "zTXt")) { - /*compressed text chunk (zTXt)*/ - if(state->decoder.read_text_chunks) { - state->error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); - if(state->error) break; - } - } else if(lodepng_chunk_type_equals(chunk, "iTXt")) { - /*international text chunk (iTXt)*/ - if(state->decoder.read_text_chunks) { - state->error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); - if(state->error) break; - } - } else if(lodepng_chunk_type_equals(chunk, "tIME")) { - state->error = readChunk_tIME(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "pHYs")) { - state->error = readChunk_pHYs(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "gAMA")) { - state->error = readChunk_gAMA(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "cHRM")) { - state->error = readChunk_cHRM(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "sRGB")) { - state->error = readChunk_sRGB(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "iCCP")) { - state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "sBIT")) { - state->error = readChunk_sBIT(&state->info_png, data, chunkLength); - if(state->error) break; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } else /*it's not an implemented chunk type, so ignore it: skip over the data*/ { - /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ - if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk)) { - CERROR_BREAK(state->error, 69); - } - - unknown = 1; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - if(state->decoder.remember_unknown_chunks) { - state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1], - &state->info_png.unknown_chunks_size[critical_pos - 1], chunk); - if(state->error) break; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } - - if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/ { - if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/ - } - - if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize); - } - - if(!state->error && state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) { - state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */ - } - - if(!state->error) { - /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation. - If the decompressed size does not match the prediction, the image must be corrupt.*/ - if(state->info_png.interlace_method == 0) { - size_t bpp = lodepng_get_bpp(&state->info_png.color); - expected_size = lodepng_get_raw_size_idat(*w, *h, bpp); - } else { - size_t bpp = lodepng_get_bpp(&state->info_png.color); - /*Adam-7 interlaced: expected size is the sum of the 7 sub-images sizes*/ - expected_size = 0; - expected_size += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, bpp); - if(*w > 4) expected_size += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, bpp); - expected_size += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, bpp); - if(*w > 2) expected_size += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, bpp); - expected_size += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, bpp); - if(*w > 1) expected_size += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, bpp); - expected_size += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, bpp); - } - - state->error = zlib_decompress(&scanlines, &scanlines_size, expected_size, idat, idatsize, &state->decoder.zlibsettings); - } - if(!state->error && scanlines_size != expected_size) state->error = 91; /*decompressed size doesn't match prediction*/ - lodepng_free(idat); - - if(!state->error) { - outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color); - *out = (unsigned char*)lodepng_malloc(outsize); - if(!*out) state->error = 83; /*alloc fail*/ - } - if(!state->error) { - lodepng_memset(*out, 0, outsize); - state->error = postProcessScanlines(*out, scanlines, *w, *h, &state->info_png); - } - lodepng_free(scanlines); -} - -unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize) { - *out = 0; - decodeGeneric(out, w, h, state, in, insize); - if(state->error) return state->error; - if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) { - /*same color type, no copying or converting of data needed*/ - /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype - the raw image has to the end user*/ - if(!state->decoder.color_convert) { - state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color); - if(state->error) return state->error; - } - } else { /*color conversion needed*/ - unsigned char* data = *out; - size_t outsize; - - /*TODO: check if this works according to the statement in the documentation: "The converter can convert - from grayscale input color type, to 8-bit grayscale or grayscale with alpha"*/ - if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA) - && !(state->info_raw.bitdepth == 8)) { - return 56; /*unsupported color mode conversion*/ - } - - outsize = lodepng_get_raw_size(*w, *h, &state->info_raw); - *out = (unsigned char*)lodepng_malloc(outsize); - if(!(*out)) { - state->error = 83; /*alloc fail*/ - } - else state->error = lodepng_convert(*out, data, &state->info_raw, - &state->info_png.color, *w, *h); - lodepng_free(data); - } - return state->error; -} - -unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, - size_t insize, LodePNGColorType colortype, unsigned bitdepth) { - unsigned error; - LodePNGState state; - lodepng_state_init(&state); - state.info_raw.colortype = colortype; - state.info_raw.bitdepth = bitdepth; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*disable reading things that this function doesn't output*/ - state.decoder.read_text_chunks = 0; - state.decoder.remember_unknown_chunks = 0; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - error = lodepng_decode(out, w, h, &state, in, insize); - lodepng_state_cleanup(&state); - return error; -} - -unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) { - return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8); -} - -unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) { - return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8); -} - -#ifdef LODEPNG_COMPILE_DISK -unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename, - LodePNGColorType colortype, unsigned bitdepth) { - unsigned char* buffer = 0; - size_t buffersize; - unsigned error; - /* safe output values in case error happens */ - *out = 0; - *w = *h = 0; - error = lodepng_load_file(&buffer, &buffersize, filename); - if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth); - lodepng_free(buffer); - return error; -} - -unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) { - return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8); -} - -unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) { - return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8); -} -#endif /*LODEPNG_COMPILE_DISK*/ - -void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) { - settings->color_convert = 1; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - settings->read_text_chunks = 1; - settings->remember_unknown_chunks = 0; - settings->max_text_size = 16777216; - settings->max_icc_size = 16777216; /* 16MB is much more than enough for any reasonable ICC profile */ -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - settings->ignore_crc = 0; - settings->ignore_critical = 0; - settings->ignore_end = 0; - lodepng_decompress_settings_init(&settings->zlibsettings); -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) - -void lodepng_state_init(LodePNGState* state) { -#ifdef LODEPNG_COMPILE_DECODER - lodepng_decoder_settings_init(&state->decoder); -#endif /*LODEPNG_COMPILE_DECODER*/ -#ifdef LODEPNG_COMPILE_ENCODER - lodepng_encoder_settings_init(&state->encoder); -#endif /*LODEPNG_COMPILE_ENCODER*/ - lodepng_color_mode_init(&state->info_raw); - lodepng_info_init(&state->info_png); - state->error = 1; -} - -void lodepng_state_cleanup(LodePNGState* state) { - lodepng_color_mode_cleanup(&state->info_raw); - lodepng_info_cleanup(&state->info_png); -} - -void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source) { - lodepng_state_cleanup(dest); - *dest = *source; - lodepng_color_mode_init(&dest->info_raw); - lodepng_info_init(&dest->info_png); - dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return; - dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return; -} - -#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ - -#ifdef LODEPNG_COMPILE_ENCODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG Encoder / */ -/* ////////////////////////////////////////////////////////////////////////// */ - - -static unsigned writeSignature(ucvector* out) { - size_t pos = out->size; - const unsigned char signature[] = {137, 80, 78, 71, 13, 10, 26, 10}; - /*8 bytes PNG signature, aka the magic bytes*/ - if(!ucvector_resize(out, out->size + 8)) return 83; /*alloc fail*/ - lodepng_memcpy(out->data + pos, signature, 8); - return 0; -} - -static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) { - unsigned char *chunk, *data; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 13, "IHDR")); - data = chunk + 8; - - lodepng_set32bitInt(data + 0, w); /*width*/ - lodepng_set32bitInt(data + 4, h); /*height*/ - data[8] = (unsigned char)bitdepth; /*bit depth*/ - data[9] = (unsigned char)colortype; /*color type*/ - data[10] = 0; /*compression method*/ - data[11] = 0; /*filter method*/ - data[12] = interlace_method; /*interlace method*/ - - lodepng_chunk_generate_crc(chunk); - return 0; -} - -/* only adds the chunk if needed (there is a key or palette with alpha) */ -static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) { - unsigned char* chunk; - size_t i, j = 8; - - if(info->palettesize == 0 || info->palettesize > 256) { - return 68; /*invalid palette size, it is only allowed to be 1-256*/ - } - - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, info->palettesize * 3, "PLTE")); - - for(i = 0; i != info->palettesize; ++i) { - /*add all channels except alpha channel*/ - chunk[j++] = info->palette[i * 4 + 0]; - chunk[j++] = info->palette[i * 4 + 1]; - chunk[j++] = info->palette[i * 4 + 2]; - } - - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info) { - unsigned char* chunk = 0; - - if(info->colortype == LCT_PALETTE) { - size_t i, amount = info->palettesize; - /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/ - for(i = info->palettesize; i != 0; --i) { - if(info->palette[4 * (i - 1) + 3] != 255) break; - --amount; - } - if(amount) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, amount, "tRNS")); - /*add the alpha channel values from the palette*/ - for(i = 0; i != amount; ++i) chunk[8 + i] = info->palette[4 * i + 3]; - } - } else if(info->colortype == LCT_GREY) { - if(info->key_defined) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "tRNS")); - chunk[8] = (unsigned char)(info->key_r >> 8); - chunk[9] = (unsigned char)(info->key_r & 255); - } - } else if(info->colortype == LCT_RGB) { - if(info->key_defined) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "tRNS")); - chunk[8] = (unsigned char)(info->key_r >> 8); - chunk[9] = (unsigned char)(info->key_r & 255); - chunk[10] = (unsigned char)(info->key_g >> 8); - chunk[11] = (unsigned char)(info->key_g & 255); - chunk[12] = (unsigned char)(info->key_b >> 8); - chunk[13] = (unsigned char)(info->key_b & 255); - } - } - - if(chunk) lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize, - LodePNGCompressSettings* zlibsettings) { - unsigned error = 0; - unsigned char* zlib = 0; - size_t zlibsize = 0; - - error = zlib_compress(&zlib, &zlibsize, data, datasize, zlibsettings); - if(!error) { - error = lodepng_chunk_createv(out, zlibsize, "IDAT", zlib); - } - lodepng_free(zlib); - return error; -} - -static unsigned addChunk_IEND(ucvector* out) { - return lodepng_chunk_createv(out, 0, "IEND", 0); -} - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - -static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) { - unsigned char* chunk = 0; - size_t keysize = lodepng_strlen(keyword), textsize = lodepng_strlen(textstring); - size_t size = keysize + 1 + textsize; - if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, size, "tEXt")); - lodepng_memcpy(chunk + 8, keyword, keysize); - chunk[8 + keysize] = 0; /*null termination char*/ - lodepng_memcpy(chunk + 9 + keysize, textstring, textsize); - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring, - LodePNGCompressSettings* zlibsettings) { - unsigned error = 0; - unsigned char* chunk = 0; - unsigned char* compressed = 0; - size_t compressedsize = 0; - size_t textsize = lodepng_strlen(textstring); - size_t keysize = lodepng_strlen(keyword); - if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ - - error = zlib_compress(&compressed, &compressedsize, - (const unsigned char*)textstring, textsize, zlibsettings); - if(!error) { - size_t size = keysize + 2 + compressedsize; - error = lodepng_chunk_init(&chunk, out, size, "zTXt"); - } - if(!error) { - lodepng_memcpy(chunk + 8, keyword, keysize); - chunk[8 + keysize] = 0; /*null termination char*/ - chunk[9 + keysize] = 0; /*compression method: 0*/ - lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize); - lodepng_chunk_generate_crc(chunk); - } - - lodepng_free(compressed); - return error; -} - -static unsigned addChunk_iTXt(ucvector* out, unsigned compress, const char* keyword, const char* langtag, - const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings) { - unsigned error = 0; - unsigned char* chunk = 0; - unsigned char* compressed = 0; - size_t compressedsize = 0; - size_t textsize = lodepng_strlen(textstring); - size_t keysize = lodepng_strlen(keyword), langsize = lodepng_strlen(langtag), transsize = lodepng_strlen(transkey); - - if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ - - if(compress) { - error = zlib_compress(&compressed, &compressedsize, - (const unsigned char*)textstring, textsize, zlibsettings); - } - if(!error) { - size_t size = keysize + 3 + langsize + 1 + transsize + 1 + (compress ? compressedsize : textsize); - error = lodepng_chunk_init(&chunk, out, size, "iTXt"); - } - if(!error) { - size_t pos = 8; - lodepng_memcpy(chunk + pos, keyword, keysize); - pos += keysize; - chunk[pos++] = 0; /*null termination char*/ - chunk[pos++] = (compress ? 1 : 0); /*compression flag*/ - chunk[pos++] = 0; /*compression method: 0*/ - lodepng_memcpy(chunk + pos, langtag, langsize); - pos += langsize; - chunk[pos++] = 0; /*null termination char*/ - lodepng_memcpy(chunk + pos, transkey, transsize); - pos += transsize; - chunk[pos++] = 0; /*null termination char*/ - if(compress) { - lodepng_memcpy(chunk + pos, compressed, compressedsize); - } else { - lodepng_memcpy(chunk + pos, textstring, textsize); - } - lodepng_chunk_generate_crc(chunk); - } - - lodepng_free(compressed); - return error; -} - -static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) { - unsigned char* chunk = 0; - if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "bKGD")); - chunk[8] = (unsigned char)(info->background_r >> 8); - chunk[9] = (unsigned char)(info->background_r & 255); - } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "bKGD")); - chunk[8] = (unsigned char)(info->background_r >> 8); - chunk[9] = (unsigned char)(info->background_r & 255); - chunk[10] = (unsigned char)(info->background_g >> 8); - chunk[11] = (unsigned char)(info->background_g & 255); - chunk[12] = (unsigned char)(info->background_b >> 8); - chunk[13] = (unsigned char)(info->background_b & 255); - } else if(info->color.colortype == LCT_PALETTE) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 1, "bKGD")); - chunk[8] = (unsigned char)(info->background_r & 255); /*palette index*/ - } - if(chunk) lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) { - unsigned char* chunk; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 7, "tIME")); - chunk[8] = (unsigned char)(time->year >> 8); - chunk[9] = (unsigned char)(time->year & 255); - chunk[10] = (unsigned char)time->month; - chunk[11] = (unsigned char)time->day; - chunk[12] = (unsigned char)time->hour; - chunk[13] = (unsigned char)time->minute; - chunk[14] = (unsigned char)time->second; - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) { - unsigned char* chunk; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 9, "pHYs")); - lodepng_set32bitInt(chunk + 8, info->phys_x); - lodepng_set32bitInt(chunk + 12, info->phys_y); - chunk[16] = info->phys_unit; - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_gAMA(ucvector* out, const LodePNGInfo* info) { - unsigned char* chunk; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "gAMA")); - lodepng_set32bitInt(chunk + 8, info->gama_gamma); - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_cHRM(ucvector* out, const LodePNGInfo* info) { - unsigned char* chunk; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 32, "cHRM")); - lodepng_set32bitInt(chunk + 8, info->chrm_white_x); - lodepng_set32bitInt(chunk + 12, info->chrm_white_y); - lodepng_set32bitInt(chunk + 16, info->chrm_red_x); - lodepng_set32bitInt(chunk + 20, info->chrm_red_y); - lodepng_set32bitInt(chunk + 24, info->chrm_green_x); - lodepng_set32bitInt(chunk + 28, info->chrm_green_y); - lodepng_set32bitInt(chunk + 32, info->chrm_blue_x); - lodepng_set32bitInt(chunk + 36, info->chrm_blue_y); - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_sRGB(ucvector* out, const LodePNGInfo* info) { - unsigned char data = info->srgb_intent; - return lodepng_chunk_createv(out, 1, "sRGB", &data); -} - -static unsigned addChunk_iCCP(ucvector* out, const LodePNGInfo* info, LodePNGCompressSettings* zlibsettings) { - unsigned error = 0; - unsigned char* chunk = 0; - unsigned char* compressed = 0; - size_t compressedsize = 0; - size_t keysize = lodepng_strlen(info->iccp_name); - - if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ - error = zlib_compress(&compressed, &compressedsize, - info->iccp_profile, info->iccp_profile_size, zlibsettings); - if(!error) { - size_t size = keysize + 2 + compressedsize; - error = lodepng_chunk_init(&chunk, out, size, "iCCP"); - } - if(!error) { - lodepng_memcpy(chunk + 8, info->iccp_name, keysize); - chunk[8 + keysize] = 0; /*null termination char*/ - chunk[9 + keysize] = 0; /*compression method: 0*/ - lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize); - lodepng_chunk_generate_crc(chunk); - } - - lodepng_free(compressed); - return error; -} - -static unsigned addChunk_sBIT(ucvector* out, const LodePNGInfo* info) { - unsigned bitdepth = (info->color.colortype == LCT_PALETTE) ? 8 : info->color.bitdepth; - unsigned char* chunk = 0; - if(info->color.colortype == LCT_GREY) { - if(info->sbit_r == 0 || info->sbit_r > bitdepth) return 115; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 1, "sBIT")); - chunk[8] = info->sbit_r; - } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_PALETTE) { - if(info->sbit_r == 0 || info->sbit_g == 0 || info->sbit_b == 0) return 115; - if(info->sbit_r > bitdepth || info->sbit_g > bitdepth || info->sbit_b > bitdepth) return 115; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 3, "sBIT")); - chunk[8] = info->sbit_r; - chunk[9] = info->sbit_g; - chunk[10] = info->sbit_b; - } else if(info->color.colortype == LCT_GREY_ALPHA) { - if(info->sbit_r == 0 || info->sbit_a == 0) return 115; - if(info->sbit_r > bitdepth || info->sbit_a > bitdepth) return 115; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "sBIT")); - chunk[8] = info->sbit_r; - chunk[9] = info->sbit_a; - } else if(info->color.colortype == LCT_RGBA) { - if(info->sbit_r == 0 || info->sbit_g == 0 || info->sbit_b == 0 || info->sbit_a == 0 || - info->sbit_r > bitdepth || info->sbit_g > bitdepth || - info->sbit_b > bitdepth || info->sbit_a > bitdepth) { - return 115; - } - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "sBIT")); - chunk[8] = info->sbit_r; - chunk[9] = info->sbit_g; - chunk[10] = info->sbit_b; - chunk[11] = info->sbit_a; - } - if(chunk) lodepng_chunk_generate_crc(chunk); - return 0; -} - -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, - size_t length, size_t bytewidth, unsigned char filterType) { - size_t i; - switch(filterType) { - case 0: /*None*/ - for(i = 0; i != length; ++i) out[i] = scanline[i]; - break; - case 1: /*Sub*/ - for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; - for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth]; - break; - case 2: /*Up*/ - if(prevline) { - for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i]; - } else { - for(i = 0; i != length; ++i) out[i] = scanline[i]; - } - break; - case 3: /*Average*/ - if(prevline) { - for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1); - for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1); - } else { - for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; - for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1); - } - break; - case 4: /*Paeth*/ - if(prevline) { - /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/ - for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]); - for(i = bytewidth; i < length; ++i) { - out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); - } - } else { - for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; - /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/ - for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]); - } - break; - default: return; /*invalid filter type given*/ - } -} - -/* integer binary logarithm, max return value is 31 */ -static size_t ilog2(size_t i) { - size_t result = 0; - if(i >= 65536) { result += 16; i >>= 16; } - if(i >= 256) { result += 8; i >>= 8; } - if(i >= 16) { result += 4; i >>= 4; } - if(i >= 4) { result += 2; i >>= 2; } - if(i >= 2) { result += 1; /*i >>= 1;*/ } - return result; -} - -/* integer approximation for i * log2(i), helper function for LFS_ENTROPY */ -static size_t ilog2i(size_t i) { - size_t l; - if(i == 0) return 0; - l = ilog2(i); - /* approximate i*log2(i): l is integer logarithm, ((i - (1u << l)) << 1u) - linearly approximates the missing fractional part multiplied by i */ - return i * l + ((i - (1u << l)) << 1u); -} - -static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, - const LodePNGColorMode* color, const LodePNGEncoderSettings* settings) { - /* - For PNG filter method 0 - out must be a buffer with as size: h + (w * h * bpp + 7u) / 8u, because there are - the scanlines with 1 extra byte per scanline - */ - - unsigned bpp = lodepng_get_bpp(color); - /*the width of a scanline in bytes, not including the filter type*/ - size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; - - /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ - size_t bytewidth = (bpp + 7u) / 8u; - const unsigned char* prevline = 0; - unsigned x, y; - unsigned error = 0; - LodePNGFilterStrategy strategy = settings->filter_strategy; - - /* - There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard: - * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. - use fixed filtering, with the filter None). - * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is - not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply - all five filters and select the filter that produces the smallest sum of absolute values per row. - This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true. - - If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed, - but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum - heuristic is used. - */ - if(settings->filter_palette_zero && - (color->colortype == LCT_PALETTE || color->bitdepth < 8)) strategy = LFS_ZERO; - - if(bpp == 0) return 31; /*error: invalid color type*/ - - if(strategy >= LFS_ZERO && strategy <= LFS_FOUR) { - unsigned char type = (unsigned char)strategy; - for(y = 0; y != h; ++y) { - size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ - size_t inindex = linebytes * y; - out[outindex] = type; /*filter type byte*/ - filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); - prevline = &in[inindex]; - } - } else if(strategy == LFS_MINSUM) { - /*adaptive filtering*/ - unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ - size_t smallest = 0; - unsigned char type, bestType = 0; - - for(type = 0; type != 5; ++type) { - attempt[type] = (unsigned char*)lodepng_malloc(linebytes); - if(!attempt[type]) error = 83; /*alloc fail*/ - } - - if(!error) { - for(y = 0; y != h; ++y) { - /*try the 5 filter types*/ - for(type = 0; type != 5; ++type) { - size_t sum = 0; - filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); - - /*calculate the sum of the result*/ - if(type == 0) { - for(x = 0; x != linebytes; ++x) sum += (unsigned char)(attempt[type][x]); - } else { - for(x = 0; x != linebytes; ++x) { - /*For differences, each byte should be treated as signed, values above 127 are negative - (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there. - This means filtertype 0 is almost never chosen, but that is justified.*/ - unsigned char s = attempt[type][x]; - sum += s < 128 ? s : (255U - s); - } - } - - /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ - if(type == 0 || sum < smallest) { - bestType = type; - smallest = sum; - } - } - - prevline = &in[y * linebytes]; - - /*now fill the out values*/ - out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; - } - } - - for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); - } else if(strategy == LFS_ENTROPY) { - unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ - size_t bestSum = 0; - unsigned type, bestType = 0; - unsigned count[256]; - - for(type = 0; type != 5; ++type) { - attempt[type] = (unsigned char*)lodepng_malloc(linebytes); - if(!attempt[type]) error = 83; /*alloc fail*/ - } - - if(!error) { - for(y = 0; y != h; ++y) { - /*try the 5 filter types*/ - for(type = 0; type != 5; ++type) { - size_t sum = 0; - filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); - lodepng_memset(count, 0, 256 * sizeof(*count)); - for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]]; - ++count[type]; /*the filter type itself is part of the scanline*/ - for(x = 0; x != 256; ++x) { - sum += ilog2i(count[x]); - } - /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ - if(type == 0 || sum > bestSum) { - bestType = type; - bestSum = sum; - } - } - - prevline = &in[y * linebytes]; - - /*now fill the out values*/ - out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; - } - } - - for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); - } else if(strategy == LFS_PREDEFINED) { - for(y = 0; y != h; ++y) { - size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ - size_t inindex = linebytes * y; - unsigned char type = settings->predefined_filters[y]; - out[outindex] = type; /*filter type byte*/ - filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); - prevline = &in[inindex]; - } - } else if(strategy == LFS_BRUTE_FORCE) { - /*brute force filter chooser. - deflate the scanline after every filter attempt to see which one deflates best. - This is very slow and gives only slightly smaller, sometimes even larger, result*/ - size_t size[5]; - unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ - size_t smallest = 0; - unsigned type = 0, bestType = 0; - unsigned char* dummy; - LodePNGCompressSettings zlibsettings; - lodepng_memcpy(&zlibsettings, &settings->zlibsettings, sizeof(LodePNGCompressSettings)); - /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, - to simulate the true case where the tree is the same for the whole image. Sometimes it gives - better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare - cases better compression. It does make this a bit less slow, so it's worth doing this.*/ - zlibsettings.btype = 1; - /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG - images only, so disable it*/ - zlibsettings.custom_zlib = 0; - zlibsettings.custom_deflate = 0; - for(type = 0; type != 5; ++type) { - attempt[type] = (unsigned char*)lodepng_malloc(linebytes); - if(!attempt[type]) error = 83; /*alloc fail*/ - } - if(!error) { - for(y = 0; y != h; ++y) /*try the 5 filter types*/ { - for(type = 0; type != 5; ++type) { - unsigned testsize = (unsigned)linebytes; - /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/ - - filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); - size[type] = 0; - dummy = 0; - zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings); - lodepng_free(dummy); - /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ - if(type == 0 || size[type] < smallest) { - bestType = type; - smallest = size[type]; - } - } - prevline = &in[y * linebytes]; - out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; - } - } - for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); - } - else return 88; /* unknown filter strategy */ - - return error; -} - -static void addPaddingBits(unsigned char* out, const unsigned char* in, - size_t olinebits, size_t ilinebits, unsigned h) { - /*The opposite of the removePaddingBits function - olinebits must be >= ilinebits*/ - unsigned y; - size_t diff = olinebits - ilinebits; - size_t obp = 0, ibp = 0; /*bit pointers*/ - for(y = 0; y != h; ++y) { - size_t x; - for(x = 0; x < ilinebits; ++x) { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - /*obp += diff; --> no, fill in some value in the padding bits too, to avoid - "Use of uninitialised value of size ###" warning from valgrind*/ - for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0); - } -} - -/* -in: non-interlaced image with size w*h -out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with - no padding bits between scanlines, but between reduced images so that each - reduced image starts at a byte. -bpp: bits per pixel -there are no padding bits, not between scanlines, not between reduced images -in has the following size in bits: w * h * bpp. -out is possibly bigger due to padding bits between reduced images -NOTE: comments about padding bits are only relevant if bpp < 8 -*/ -static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { - unsigned passw[7], passh[7]; - size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - if(bpp >= 8) { - for(i = 0; i != 7; ++i) { - unsigned x, y, b; - size_t bytewidth = bpp / 8u; - for(y = 0; y < passh[i]; ++y) - for(x = 0; x < passw[i]; ++x) { - size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; - size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; - for(b = 0; b < bytewidth; ++b) { - out[pixeloutstart + b] = in[pixelinstart + b]; - } - } - } - } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ { - for(i = 0; i != 7; ++i) { - unsigned x, y, b; - unsigned ilinebits = bpp * passw[i]; - unsigned olinebits = bpp * w; - size_t obp, ibp; /*bit pointers (for out and in buffer)*/ - for(y = 0; y < passh[i]; ++y) - for(x = 0; x < passw[i]; ++x) { - ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; - obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); - for(b = 0; b < bpp; ++b) { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - } - } - } -} - -/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image. -return value is error**/ -static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in, - unsigned w, unsigned h, - const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings) { - /* - This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: - *) if no Adam7: 1) add padding bits (= possible extra bits per scanline if bpp < 8) 2) filter - *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter - */ - unsigned bpp = lodepng_get_bpp(&info_png->color); - unsigned error = 0; - - if(info_png->interlace_method == 0) { - *outsize = h + (h * ((w * bpp + 7u) / 8u)); /*image size plus an extra byte per scanline + possible padding bits*/ - *out = (unsigned char*)lodepng_malloc(*outsize); - if(!(*out) && (*outsize)) error = 83; /*alloc fail*/ - - if(!error) { - /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ - if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) { - unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7u) / 8u)); - if(!padded) error = 83; /*alloc fail*/ - if(!error) { - addPaddingBits(padded, in, ((w * bpp + 7u) / 8u) * 8u, w * bpp, h); - error = filter(*out, padded, w, h, &info_png->color, settings); - } - lodepng_free(padded); - } else { - /*we can immediately filter into the out buffer, no other steps needed*/ - error = filter(*out, in, w, h, &info_png->color, settings); - } - } - } else /*interlace_method is 1 (Adam7)*/ { - unsigned passw[7], passh[7]; - size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned char* adam7; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ - *out = (unsigned char*)lodepng_malloc(*outsize); - if(!(*out)) error = 83; /*alloc fail*/ - - adam7 = (unsigned char*)lodepng_malloc(passstart[7]); - if(!adam7 && passstart[7]) error = 83; /*alloc fail*/ - - if(!error) { - unsigned i; - - Adam7_interlace(adam7, in, w, h, bpp); - for(i = 0; i != 7; ++i) { - if(bpp < 8) { - unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]); - if(!padded) ERROR_BREAK(83); /*alloc fail*/ - addPaddingBits(padded, &adam7[passstart[i]], - ((passw[i] * bpp + 7u) / 8u) * 8u, passw[i] * bpp, passh[i]); - error = filter(&(*out)[filter_passstart[i]], padded, - passw[i], passh[i], &info_png->color, settings); - lodepng_free(padded); - } else { - error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], - passw[i], passh[i], &info_png->color, settings); - } - - if(error) break; - } - } - - lodepng_free(adam7); - } - - return error; -} - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) { - unsigned char* inchunk = data; - while((size_t)(inchunk - data) < datasize) { - CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk)); - out->allocsize = out->size; /*fix the allocsize again*/ - inchunk = lodepng_chunk_next(inchunk, data + datasize); - } - return 0; -} - -static unsigned isGrayICCProfile(const unsigned char* profile, unsigned size) { - /* - It is a gray profile if bytes 16-19 are "GRAY", rgb profile if bytes 16-19 - are "RGB ". We do not perform any full parsing of the ICC profile here, other - than check those 4 bytes to grayscale profile. Other than that, validity of - the profile is not checked. This is needed only because the PNG specification - requires using a non-gray color model if there is an ICC profile with "RGB " - (sadly limiting compression opportunities if the input data is grayscale RGB - data), and requires using a gray color model if it is "GRAY". - */ - if(size < 20) return 0; - return profile[16] == 'G' && profile[17] == 'R' && profile[18] == 'A' && profile[19] == 'Y'; -} - -static unsigned isRGBICCProfile(const unsigned char* profile, unsigned size) { - /* See comment in isGrayICCProfile*/ - if(size < 20) return 0; - return profile[16] == 'R' && profile[17] == 'G' && profile[18] == 'B' && profile[19] == ' '; -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -unsigned lodepng_encode(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h, - LodePNGState* state) { - unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ - size_t datasize = 0; - ucvector outv = ucvector_init(NULL, 0); - LodePNGInfo info; - const LodePNGInfo* info_png = &state->info_png; - LodePNGColorMode auto_color; - - lodepng_info_init(&info); - lodepng_color_mode_init(&auto_color); - - /*provide some proper output values if error will happen*/ - *out = 0; - *outsize = 0; - state->error = 0; - - /*check input values validity*/ - if((info_png->color.colortype == LCT_PALETTE || state->encoder.force_palette) - && (info_png->color.palettesize == 0 || info_png->color.palettesize > 256)) { - /*this error is returned even if auto_convert is enabled and thus encoder could - generate the palette by itself: while allowing this could be possible in theory, - it may complicate the code or edge cases, and always requiring to give a palette - when setting this color type is a simpler contract*/ - state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/ - goto cleanup; - } - if(state->encoder.zlibsettings.btype > 2) { - state->error = 61; /*error: invalid btype*/ - goto cleanup; - } - if(info_png->interlace_method > 1) { - state->error = 71; /*error: invalid interlace mode*/ - goto cleanup; - } - state->error = checkColorValidity(info_png->color.colortype, info_png->color.bitdepth); - if(state->error) goto cleanup; /*error: invalid color type given*/ - state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth); - if(state->error) goto cleanup; /*error: invalid color type given*/ - - /* color convert and compute scanline filter types */ - lodepng_info_copy(&info, &state->info_png); - if(state->encoder.auto_convert) { - LodePNGColorStats stats; - unsigned allow_convert = 1; - lodepng_color_stats_init(&stats); -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - if(info_png->iccp_defined && - isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) { - /*the PNG specification does not allow to use palette with a GRAY ICC profile, even - if the palette has only gray colors, so disallow it.*/ - stats.allow_palette = 0; - } - if(info_png->iccp_defined && - isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) { - /*the PNG specification does not allow to use grayscale color with RGB ICC profile, so disallow gray.*/ - stats.allow_greyscale = 0; - } -#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ - state->error = lodepng_compute_color_stats(&stats, image, w, h, &state->info_raw); - if(state->error) goto cleanup; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - if(info_png->background_defined) { - /*the background chunk's color must be taken into account as well*/ - unsigned r = 0, g = 0, b = 0; - LodePNGColorMode mode16 = lodepng_color_mode_make(LCT_RGB, 16); - lodepng_convert_rgb(&r, &g, &b, - info_png->background_r, info_png->background_g, info_png->background_b, &mode16, &info_png->color); - state->error = lodepng_color_stats_add(&stats, r, g, b, 65535); - if(state->error) goto cleanup; - } -#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ - state->error = auto_choose_color(&auto_color, &state->info_raw, &stats); - if(state->error) goto cleanup; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - if(info_png->sbit_defined) { - /*if sbit is defined, due to strict requirements of which sbit values can be present for which color modes, - auto_convert can't be done in many cases. However, do support a few cases here. - TODO: more conversions may be possible, and it may also be possible to get a more appropriate color type out of - auto_choose_color if knowledge about sbit is used beforehand - */ - unsigned sbit_max = LODEPNG_MAX(LODEPNG_MAX(LODEPNG_MAX(info_png->sbit_r, info_png->sbit_g), - info_png->sbit_b), info_png->sbit_a); - unsigned equal = (!info_png->sbit_g || info_png->sbit_g == info_png->sbit_r) - && (!info_png->sbit_b || info_png->sbit_b == info_png->sbit_r) - && (!info_png->sbit_a || info_png->sbit_a == info_png->sbit_r); - allow_convert = 0; - if(info.color.colortype == LCT_PALETTE && - auto_color.colortype == LCT_PALETTE) { - /* input and output are palette, and in this case it may happen that palette data is - expected to be copied from info_raw into the info_png */ - allow_convert = 1; - } - /*going from 8-bit RGB to palette (or 16-bit as long as sbit_max <= 8) is possible - since both are 8-bit RGB for sBIT's purposes*/ - if(info.color.colortype == LCT_RGB && - auto_color.colortype == LCT_PALETTE && sbit_max <= 8) { - allow_convert = 1; - } - /*going from 8-bit RGBA to palette is also ok but only if sbit_a is exactly 8*/ - if(info.color.colortype == LCT_RGBA && auto_color.colortype == LCT_PALETTE && - info_png->sbit_a == 8 && sbit_max <= 8) { - allow_convert = 1; - } - /*going from 16-bit RGB(A) to 8-bit RGB(A) is ok if all sbit values are <= 8*/ - if((info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA) && info.color.bitdepth == 16 && - auto_color.colortype == info.color.colortype && auto_color.bitdepth == 8 && - sbit_max <= 8) { - allow_convert = 1; - } - /*going to less channels is ok if all bit values are equal (all possible values in sbit, - as well as the chosen bitdepth of the result). Due to how auto_convert works, - we already know that auto_color.colortype has less than or equal amount of channels than - info.colortype. Palette is not used here. This conversion is not allowed if - info_png->sbit_r < auto_color.bitdepth, because specifically for alpha, non-presence of - an sbit value heavily implies that alpha's bit depth is equal to the PNG bit depth (rather - than the bit depths set in the r, g and b sbit values, by how the PNG specification describes - handling tRNS chunk case with sBIT), so be conservative here about ignoring user input.*/ - if(info.color.colortype != LCT_PALETTE && auto_color.colortype != LCT_PALETTE && - equal && info_png->sbit_r == auto_color.bitdepth) { - allow_convert = 1; - } - } -#endif - if(state->encoder.force_palette) { - if(info.color.colortype != LCT_GREY && info.color.colortype != LCT_GREY_ALPHA && - (auto_color.colortype == LCT_GREY || auto_color.colortype == LCT_GREY_ALPHA)) { - /*user speficially forced a PLTE palette, so cannot convert to grayscale types because - the PNG specification only allows writing a suggested palette in PLTE for truecolor types*/ - allow_convert = 0; - } - } - if(allow_convert) { - lodepng_color_mode_copy(&info.color, &auto_color); -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*also convert the background chunk*/ - if(info_png->background_defined) { - if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b, - info_png->background_r, info_png->background_g, info_png->background_b, &info.color, &info_png->color)) { - state->error = 104; - goto cleanup; - } - } -#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ - } - } -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - if(info_png->iccp_defined) { - unsigned gray_icc = isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size); - unsigned rgb_icc = isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size); - unsigned gray_png = info.color.colortype == LCT_GREY || info.color.colortype == LCT_GREY_ALPHA; - if(!gray_icc && !rgb_icc) { - state->error = 100; /* Disallowed profile color type for PNG */ - goto cleanup; - } - if(gray_icc != gray_png) { - /*Not allowed to use RGB/RGBA/palette with GRAY ICC profile or vice versa, - or in case of auto_convert, it wasn't possible to find appropriate model*/ - state->error = state->encoder.auto_convert ? 102 : 101; - goto cleanup; - } - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) { - unsigned char* converted; - size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7u) / 8u; - - converted = (unsigned char*)lodepng_malloc(size); - if(!converted && size) state->error = 83; /*alloc fail*/ - if(!state->error) { - state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h); - } - if(!state->error) { - state->error = preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder); - } - lodepng_free(converted); - if(state->error) goto cleanup; - } else { - state->error = preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder); - if(state->error) goto cleanup; - } - - /* output all PNG chunks */ { -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - size_t i; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - /*write signature and chunks*/ - state->error = writeSignature(&outv); - if(state->error) goto cleanup; - /*IHDR*/ - state->error = addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method); - if(state->error) goto cleanup; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*unknown chunks between IHDR and PLTE*/ - if(info.unknown_chunks_data[0]) { - state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]); - if(state->error) goto cleanup; - } - /*color profile chunks must come before PLTE */ - if(info.iccp_defined) { - state->error = addChunk_iCCP(&outv, &info, &state->encoder.zlibsettings); - if(state->error) goto cleanup; - } - if(info.srgb_defined) { - state->error = addChunk_sRGB(&outv, &info); - if(state->error) goto cleanup; - } - if(info.gama_defined) { - state->error = addChunk_gAMA(&outv, &info); - if(state->error) goto cleanup; - } - if(info.chrm_defined) { - state->error = addChunk_cHRM(&outv, &info); - if(state->error) goto cleanup; - } - if(info_png->sbit_defined) { - state->error = addChunk_sBIT(&outv, &info); - if(state->error) goto cleanup; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - /*PLTE*/ - if(info.color.colortype == LCT_PALETTE) { - state->error = addChunk_PLTE(&outv, &info.color); - if(state->error) goto cleanup; - } - if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) { - /*force_palette means: write suggested palette for truecolor in PLTE chunk*/ - state->error = addChunk_PLTE(&outv, &info.color); - if(state->error) goto cleanup; - } - /*tRNS (this will only add if when necessary) */ - state->error = addChunk_tRNS(&outv, &info.color); - if(state->error) goto cleanup; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*bKGD (must come between PLTE and the IDAt chunks*/ - if(info.background_defined) { - state->error = addChunk_bKGD(&outv, &info); - if(state->error) goto cleanup; - } - /*pHYs (must come before the IDAT chunks)*/ - if(info.phys_defined) { - state->error = addChunk_pHYs(&outv, &info); - if(state->error) goto cleanup; - } - - /*unknown chunks between PLTE and IDAT*/ - if(info.unknown_chunks_data[1]) { - state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]); - if(state->error) goto cleanup; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - /*IDAT (multiple IDAT chunks must be consecutive)*/ - state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings); - if(state->error) goto cleanup; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*tIME*/ - if(info.time_defined) { - state->error = addChunk_tIME(&outv, &info.time); - if(state->error) goto cleanup; - } - /*tEXt and/or zTXt*/ - for(i = 0; i != info.text_num; ++i) { - if(lodepng_strlen(info.text_keys[i]) > 79) { - state->error = 66; /*text chunk too large*/ - goto cleanup; - } - if(lodepng_strlen(info.text_keys[i]) < 1) { - state->error = 67; /*text chunk too small*/ - goto cleanup; - } - if(state->encoder.text_compression) { - state->error = addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings); - if(state->error) goto cleanup; - } else { - state->error = addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]); - if(state->error) goto cleanup; - } - } - /*LodePNG version id in text chunk*/ - if(state->encoder.add_id) { - unsigned already_added_id_text = 0; - for(i = 0; i != info.text_num; ++i) { - const char* k = info.text_keys[i]; - /* Could use strcmp, but we're not calling or reimplementing this C library function for this use only */ - if(k[0] == 'L' && k[1] == 'o' && k[2] == 'd' && k[3] == 'e' && - k[4] == 'P' && k[5] == 'N' && k[6] == 'G' && k[7] == '\0') { - already_added_id_text = 1; - break; - } - } - if(already_added_id_text == 0) { - state->error = addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/ - if(state->error) goto cleanup; - } - } - /*iTXt*/ - for(i = 0; i != info.itext_num; ++i) { - if(lodepng_strlen(info.itext_keys[i]) > 79) { - state->error = 66; /*text chunk too large*/ - goto cleanup; - } - if(lodepng_strlen(info.itext_keys[i]) < 1) { - state->error = 67; /*text chunk too small*/ - goto cleanup; - } - state->error = addChunk_iTXt( - &outv, state->encoder.text_compression, - info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i], - &state->encoder.zlibsettings); - if(state->error) goto cleanup; - } - - /*unknown chunks between IDAT and IEND*/ - if(info.unknown_chunks_data[2]) { - state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]); - if(state->error) goto cleanup; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - state->error = addChunk_IEND(&outv); - if(state->error) goto cleanup; - } - -cleanup: - lodepng_info_cleanup(&info); - lodepng_free(data); - lodepng_color_mode_cleanup(&auto_color); - - /*instead of cleaning the vector up, give it to the output*/ - *out = outv.data; - *outsize = outv.size; - - return state->error; -} - -unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image, - unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) { - unsigned error; - LodePNGState state; - lodepng_state_init(&state); - state.info_raw.colortype = colortype; - state.info_raw.bitdepth = bitdepth; - state.info_png.color.colortype = colortype; - state.info_png.color.bitdepth = bitdepth; - lodepng_encode(out, outsize, image, w, h, &state); - error = state.error; - lodepng_state_cleanup(&state); - return error; -} - -unsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) { - return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8); -} - -unsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) { - return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8); -} - -#ifdef LODEPNG_COMPILE_DISK -unsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) { - unsigned char* buffer; - size_t buffersize; - unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth); - if(!error) error = lodepng_save_file(buffer, buffersize, filename); - lodepng_free(buffer); - return error; -} - -unsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) { - return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8); -} - -unsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) { - return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8); -} -#endif /*LODEPNG_COMPILE_DISK*/ - -void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings) { - lodepng_compress_settings_init(&settings->zlibsettings); - settings->filter_palette_zero = 1; - settings->filter_strategy = LFS_MINSUM; - settings->auto_convert = 1; - settings->force_palette = 0; - settings->predefined_filters = 0; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - settings->add_id = 0; - settings->text_compression = 1; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} - -#endif /*LODEPNG_COMPILE_ENCODER*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -#ifdef LODEPNG_COMPILE_ERROR_TEXT -/* -This returns the description of a numerical error code in English. This is also -the documentation of all the error codes. -*/ -const char* lodepng_error_text(unsigned code) { - switch(code) { - case 0: return "no error, everything went ok"; - case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/ - case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/ - case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/ - case 13: return "problem while processing dynamic deflate block"; - case 14: return "problem while processing dynamic deflate block"; - case 15: return "problem while processing dynamic deflate block"; - /*this error could happen if there are only 0 or 1 symbols present in the huffman code:*/ - case 16: return "invalid code while processing dynamic deflate block"; - case 17: return "end of out buffer memory reached while inflating"; - case 18: return "invalid distance code while inflating"; - case 19: return "end of out buffer memory reached while inflating"; - case 20: return "invalid deflate block BTYPE encountered while decoding"; - case 21: return "NLEN is not ones complement of LEN in a deflate block"; - - /*end of out buffer memory reached while inflating: - This can happen if the inflated deflate data is longer than the amount of bytes required to fill up - all the pixels of the image, given the color depth and image dimensions. Something that doesn't - happen in a normal, well encoded, PNG image.*/ - case 22: return "end of out buffer memory reached while inflating"; - case 23: return "end of in buffer memory reached while inflating"; - case 24: return "invalid FCHECK in zlib header"; - case 25: return "invalid compression method in zlib header"; - case 26: return "FDICT encountered in zlib header while it's not used for PNG"; - case 27: return "PNG file is smaller than a PNG header"; - /*Checks the magic file header, the first 8 bytes of the PNG file*/ - case 28: return "incorrect PNG signature, it's no PNG or corrupted"; - case 29: return "first chunk is not the header chunk"; - case 30: return "chunk length too large, chunk broken off at end of file"; - case 31: return "illegal PNG color type or bpp"; - case 32: return "illegal PNG compression method"; - case 33: return "illegal PNG filter method"; - case 34: return "illegal PNG interlace method"; - case 35: return "chunk length of a chunk is too large or the chunk too small"; - case 36: return "illegal PNG filter type encountered"; - case 37: return "illegal bit depth for this color type given"; - case 38: return "the palette is too small or too big"; /*0, or more than 256 colors*/ - case 39: return "tRNS chunk before PLTE or has more entries than palette size"; - case 40: return "tRNS chunk has wrong size for grayscale image"; - case 41: return "tRNS chunk has wrong size for RGB image"; - case 42: return "tRNS chunk appeared while it was not allowed for this color type"; - case 43: return "bKGD chunk has wrong size for palette image"; - case 44: return "bKGD chunk has wrong size for grayscale image"; - case 45: return "bKGD chunk has wrong size for RGB image"; - case 48: return "empty input buffer given to decoder. Maybe caused by non-existing file?"; - case 49: return "jumped past memory while generating dynamic huffman tree"; - case 50: return "jumped past memory while generating dynamic huffman tree"; - case 51: return "jumped past memory while inflating huffman block"; - case 52: return "jumped past memory while inflating"; - case 53: return "size of zlib data too small"; - case 54: return "repeat symbol in tree while there was no value symbol yet"; - /*jumped past tree while generating huffman tree, this could be when the - tree will have more leaves than symbols after generating it out of the - given lengths. They call this an oversubscribed dynamic bit lengths tree in zlib.*/ - case 55: return "jumped past tree while generating huffman tree"; - case 56: return "given output image colortype or bitdepth not supported for color conversion"; - case 57: return "invalid CRC encountered (checking CRC can be disabled)"; - case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)"; - case 59: return "requested color conversion not supported"; - case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)"; - case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)"; - /*LodePNG leaves the choice of RGB to grayscale conversion formula to the user.*/ - case 62: return "conversion from color to grayscale not supported"; - /*(2^31-1)*/ - case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk"; - /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/ - case 64: return "the length of the END symbol 256 in the Huffman tree is 0"; - case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes"; - case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte"; - case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors"; - case 69: return "unknown chunk type with 'critical' flag encountered by the decoder"; - case 71: return "invalid interlace mode given to encoder (must be 0 or 1)"; - case 72: return "while decoding, invalid compression method encountering in zTXt or iTXt chunk (it must be 0)"; - case 73: return "invalid tIME chunk size"; - case 74: return "invalid pHYs chunk size"; - /*length could be wrong, or data chopped off*/ - case 75: return "no null termination char found while decoding text chunk"; - case 76: return "iTXt chunk too short to contain required bytes"; - case 77: return "integer overflow in buffer size"; - case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/ - case 79: return "failed to open file for writing"; - case 80: return "tried creating a tree of 0 symbols"; - case 81: return "lazy matching at pos 0 is impossible"; - case 82: return "color conversion to palette requested while a color isn't in palette, or index out of bounds"; - case 83: return "memory allocation failed"; - case 84: return "given image too small to contain all pixels to be encoded"; - case 86: return "impossible offset in lz77 encoding (internal bug)"; - case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined"; - case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy"; - case 89: return "text chunk keyword too short or long: must have size 1-79"; - /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/ - case 90: return "windowsize must be a power of two"; - case 91: return "invalid decompressed idat size"; - case 92: return "integer overflow due to too many pixels"; - case 93: return "zero width or height is invalid"; - case 94: return "header chunk must have a size of 13 bytes"; - case 95: return "integer overflow with combined idat chunk size"; - case 96: return "invalid gAMA chunk size"; - case 97: return "invalid cHRM chunk size"; - case 98: return "invalid sRGB chunk size"; - case 99: return "invalid sRGB rendering intent"; - case 100: return "invalid ICC profile color type, the PNG specification only allows RGB or GRAY"; - case 101: return "PNG specification does not allow RGB ICC profile on gray color types and vice versa"; - case 102: return "not allowed to set grayscale ICC profile with colored pixels by PNG specification"; - case 103: return "invalid palette index in bKGD chunk. Maybe it came before PLTE chunk?"; - case 104: return "invalid bKGD color while encoding (e.g. palette index out of range)"; - case 105: return "integer overflow of bitsize"; - case 106: return "PNG file must have PLTE chunk if color type is palette"; - case 107: return "color convert from palette mode requested without setting the palette data in it"; - case 108: return "tried to add more than 256 values to a palette"; - /*this limit can be configured in LodePNGDecompressSettings*/ - case 109: return "tried to decompress zlib or deflate data larger than desired max_output_size"; - case 110: return "custom zlib or inflate decompression failed"; - case 111: return "custom zlib or deflate compression failed"; - /*max text size limit can be configured in LodePNGDecoderSettings. This error prevents - unreasonable memory consumption when decoding due to impossibly large text sizes.*/ - case 112: return "compressed text unreasonably large"; - /*max ICC size limit can be configured in LodePNGDecoderSettings. This error prevents - unreasonable memory consumption when decoding due to impossibly large ICC profile*/ - case 113: return "ICC profile unreasonably large"; - case 114: return "sBIT chunk has wrong size for the color type of the image"; - case 115: return "sBIT value out of range"; - } - return "unknown error code"; -} -#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // C++ Wrapper // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_CPP -namespace lodepng { - -#ifdef LODEPNG_COMPILE_DISK -unsigned load_file(std::vector& buffer, const std::string& filename) { - long size = lodepng_filesize(filename.c_str()); - if(size < 0) return 78; - buffer.resize((size_t)size); - return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str()); -} - -/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ -unsigned save_file(const std::vector& buffer, const std::string& filename) { - return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str()); -} -#endif /* LODEPNG_COMPILE_DISK */ - -#ifdef LODEPNG_COMPILE_ZLIB -#ifdef LODEPNG_COMPILE_DECODER -unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGDecompressSettings& settings) { - unsigned char* buffer = 0; - size_t buffersize = 0; - unsigned error = zlib_decompress(&buffer, &buffersize, 0, in, insize, &settings); - if(buffer) { - out.insert(out.end(), buffer, &buffer[buffersize]); - lodepng_free(buffer); - } - return error; -} - -unsigned decompress(std::vector& out, const std::vector& in, - const LodePNGDecompressSettings& settings) { - return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings); -} -#endif /* LODEPNG_COMPILE_DECODER */ - -#ifdef LODEPNG_COMPILE_ENCODER -unsigned compress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGCompressSettings& settings) { - unsigned char* buffer = 0; - size_t buffersize = 0; - unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings); - if(buffer) { - out.insert(out.end(), buffer, &buffer[buffersize]); - lodepng_free(buffer); - } - return error; -} - -unsigned compress(std::vector& out, const std::vector& in, - const LodePNGCompressSettings& settings) { - return compress(out, in.empty() ? 0 : &in[0], in.size(), settings); -} -#endif /* LODEPNG_COMPILE_ENCODER */ -#endif /* LODEPNG_COMPILE_ZLIB */ - - -#ifdef LODEPNG_COMPILE_PNG - -State::State() { - lodepng_state_init(this); -} - -State::State(const State& other) { - lodepng_state_init(this); - lodepng_state_copy(this, &other); -} - -State::~State() { - lodepng_state_cleanup(this); -} - -State& State::operator=(const State& other) { - lodepng_state_copy(this, &other); - return *this; -} - -#ifdef LODEPNG_COMPILE_DECODER - -unsigned decode(std::vector& out, unsigned& w, unsigned& h, const unsigned char* in, - size_t insize, LodePNGColorType colortype, unsigned bitdepth) { - unsigned char* buffer = 0; - unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth); - if(buffer && !error) { - State state; - state.info_raw.colortype = colortype; - state.info_raw.bitdepth = bitdepth; - size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); - out.insert(out.end(), buffer, &buffer[buffersize]); - } - lodepng_free(buffer); - return error; -} - -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const std::vector& in, LodePNGColorType colortype, unsigned bitdepth) { - return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth); -} - -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const unsigned char* in, size_t insize) { - unsigned char* buffer = NULL; - unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize); - if(buffer && !error) { - size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); - out.insert(out.end(), buffer, &buffer[buffersize]); - } - lodepng_free(buffer); - return error; -} - -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const std::vector& in) { - return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size()); -} - -#ifdef LODEPNG_COMPILE_DISK -unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::string& filename, - LodePNGColorType colortype, unsigned bitdepth) { - std::vector buffer; - /* safe output values in case error happens */ - w = h = 0; - unsigned error = load_file(buffer, filename); - if(error) return error; - return decode(out, w, h, buffer, colortype, bitdepth); -} -#endif /* LODEPNG_COMPILE_DECODER */ -#endif /* LODEPNG_COMPILE_DISK */ - -#ifdef LODEPNG_COMPILE_ENCODER -unsigned encode(std::vector& out, const unsigned char* in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) { - unsigned char* buffer; - size_t buffersize; - unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth); - if(buffer) { - out.insert(out.end(), buffer, &buffer[buffersize]); - lodepng_free(buffer); - } - return error; -} - -unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) { - if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; - return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); -} - -unsigned encode(std::vector& out, - const unsigned char* in, unsigned w, unsigned h, - State& state) { - unsigned char* buffer; - size_t buffersize; - unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state); - if(buffer) { - out.insert(out.end(), buffer, &buffer[buffersize]); - lodepng_free(buffer); - } - return error; -} - -unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - State& state) { - if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84; - return encode(out, in.empty() ? 0 : &in[0], w, h, state); -} - -#ifdef LODEPNG_COMPILE_DISK -unsigned encode(const std::string& filename, - const unsigned char* in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) { - std::vector buffer; - unsigned error = encode(buffer, in, w, h, colortype, bitdepth); - if(!error) error = save_file(buffer, filename); - return error; -} - -unsigned encode(const std::string& filename, - const std::vector& in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) { - if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; - return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); -} -#endif /* LODEPNG_COMPILE_DISK */ -#endif /* LODEPNG_COMPILE_ENCODER */ -#endif /* LODEPNG_COMPILE_PNG */ -} /* namespace lodepng */ -#endif /*LODEPNG_COMPILE_CPP*/ diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/resources/lodepng.h --- a/src/semicongine/resources/lodepng.h Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2089 +0,0 @@ -/* -LodePNG version 20230410 - -Copyright (c) 2005-2023 Lode Vandevenne - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*/ - -#ifndef LODEPNG_H -#define LODEPNG_H - -#include /*for size_t*/ - -extern const char* LODEPNG_VERSION_STRING; - -/* -The following #defines are used to create code sections. They can be disabled -to disable code sections, which can give faster compile time and smaller binary. -The "NO_COMPILE" defines are designed to be used to pass as defines to the -compiler command to disable them without modifying this header, e.g. --DLODEPNG_NO_COMPILE_ZLIB for gcc or clang. -*/ -/*deflate & zlib. If disabled, you must specify alternative zlib functions in -the custom_zlib field of the compress and decompress settings*/ -#ifndef LODEPNG_NO_COMPILE_ZLIB -/*pass -DLODEPNG_NO_COMPILE_ZLIB to the compiler to disable this, or comment out LODEPNG_COMPILE_ZLIB below*/ -#define LODEPNG_COMPILE_ZLIB -#endif - -/*png encoder and png decoder*/ -#ifndef LODEPNG_NO_COMPILE_PNG -/*pass -DLODEPNG_NO_COMPILE_PNG to the compiler to disable this, or comment out LODEPNG_COMPILE_PNG below*/ -#define LODEPNG_COMPILE_PNG -#endif - -/*deflate&zlib decoder and png decoder*/ -#ifndef LODEPNG_NO_COMPILE_DECODER -/*pass -DLODEPNG_NO_COMPILE_DECODER to the compiler to disable this, or comment out LODEPNG_COMPILE_DECODER below*/ -#define LODEPNG_COMPILE_DECODER -#endif - -/*deflate&zlib encoder and png encoder*/ -#ifndef LODEPNG_NO_COMPILE_ENCODER -/*pass -DLODEPNG_NO_COMPILE_ENCODER to the compiler to disable this, or comment out LODEPNG_COMPILE_ENCODER below*/ -#define LODEPNG_COMPILE_ENCODER -#endif - -/*the optional built in harddisk file loading and saving functions*/ -#ifndef LODEPNG_NO_COMPILE_DISK -/*pass -DLODEPNG_NO_COMPILE_DISK to the compiler to disable this, or comment out LODEPNG_COMPILE_DISK below*/ -#define LODEPNG_COMPILE_DISK -#endif - -/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/ -#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS -/*pass -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS to the compiler to disable this, -or comment out LODEPNG_COMPILE_ANCILLARY_CHUNKS below*/ -#define LODEPNG_COMPILE_ANCILLARY_CHUNKS -#endif - -/*ability to convert error numerical codes to English text string*/ -#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT -/*pass -DLODEPNG_NO_COMPILE_ERROR_TEXT to the compiler to disable this, -or comment out LODEPNG_COMPILE_ERROR_TEXT below*/ -#define LODEPNG_COMPILE_ERROR_TEXT -#endif - -/*Compile the default allocators (C's free, malloc and realloc). If you disable this, -you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your -source files with custom allocators.*/ -#ifndef LODEPNG_NO_COMPILE_ALLOCATORS -/*pass -DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler to disable the built-in ones, -or comment out LODEPNG_COMPILE_ALLOCATORS below*/ -#define LODEPNG_COMPILE_ALLOCATORS -#endif - -/*Disable built-in CRC function, in that case a custom implementation of -lodepng_crc32 must be defined externally so that it can be linked in. -The default built-in CRC code comes with 8KB of lookup tables, so for memory constrained environment you may want it -disabled and provide a much smaller implementation externally as said above. You can find such an example implementation -in a comment in the lodepng.c(pp) file in the 'else' case of the searchable LODEPNG_COMPILE_CRC section.*/ -#ifndef LODEPNG_NO_COMPILE_CRC -/*pass -DLODEPNG_NO_COMPILE_CRC to the compiler to disable the built-in one, -or comment out LODEPNG_COMPILE_CRC below*/ -#define LODEPNG_COMPILE_CRC -#endif - -/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/ -#ifdef __cplusplus -#ifndef LODEPNG_NO_COMPILE_CPP -/*pass -DLODEPNG_NO_COMPILE_CPP to the compiler to disable C++ (not needed if a C-only compiler), -or comment out LODEPNG_COMPILE_CPP below*/ -#define LODEPNG_COMPILE_CPP -#endif -#endif - -#ifdef LODEPNG_COMPILE_CPP -#include -#include -#endif /*LODEPNG_COMPILE_CPP*/ - -#ifdef LODEPNG_COMPILE_PNG -/*The PNG color types (also used for raw image).*/ -typedef enum LodePNGColorType { - LCT_GREY = 0, /*grayscale: 1,2,4,8,16 bit*/ - LCT_RGB = 2, /*RGB: 8,16 bit*/ - LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/ - LCT_GREY_ALPHA = 4, /*grayscale with alpha: 8,16 bit*/ - LCT_RGBA = 6, /*RGB with alpha: 8,16 bit*/ - /*LCT_MAX_OCTET_VALUE lets the compiler allow this enum to represent any invalid - byte value from 0 to 255 that could be present in an invalid PNG file header. Do - not use, compare with or set the name LCT_MAX_OCTET_VALUE, instead either use - the valid color type names above, or numeric values like 1 or 7 when checking for - particular disallowed color type byte values, or cast to integer to print it.*/ - LCT_MAX_OCTET_VALUE = 255 -} LodePNGColorType; - -#ifdef LODEPNG_COMPILE_DECODER -/* -Converts PNG data in memory to raw pixel data. -out: Output parameter. Pointer to buffer that will contain the raw pixel data. - After decoding, its size is w * h * (bytes per pixel) bytes larger than - initially. Bytes per pixel depends on colortype and bitdepth. - Must be freed after usage with free(*out). - Note: for 16-bit per channel colors, uses big endian format like PNG does. -w: Output parameter. Pointer to width of pixel data. -h: Output parameter. Pointer to height of pixel data. -in: Memory buffer with the PNG file. -insize: size of the in buffer. -colortype: the desired color type for the raw output image. See explanation on PNG color types. -bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types. -Return value: LodePNG error code (0 means no error). -*/ -unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, - const unsigned char* in, size_t insize, - LodePNGColorType colortype, unsigned bitdepth); - -/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/ -unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, - const unsigned char* in, size_t insize); - -/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/ -unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, - const unsigned char* in, size_t insize); - -#ifdef LODEPNG_COMPILE_DISK -/* -Load PNG from disk, from file with given name. -Same as the other decode functions, but instead takes a filename as input. - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and decode in-memory.*/ -unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, - const char* filename, - LodePNGColorType colortype, unsigned bitdepth); - -/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image. - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and decode in-memory.*/ -unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, - const char* filename); - -/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image. - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and decode in-memory.*/ -unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, - const char* filename); -#endif /*LODEPNG_COMPILE_DISK*/ -#endif /*LODEPNG_COMPILE_DECODER*/ - - -#ifdef LODEPNG_COMPILE_ENCODER -/* -Converts raw pixel data into a PNG image in memory. The colortype and bitdepth - of the output PNG image cannot be chosen, they are automatically determined - by the colortype, bitdepth and content of the input pixel data. - Note: for 16-bit per channel colors, needs big endian format like PNG does. -out: Output parameter. Pointer to buffer that will contain the PNG image data. - Must be freed after usage with free(*out). -outsize: Output parameter. Pointer to the size in bytes of the out buffer. -image: The raw pixel data to encode. The size of this buffer should be - w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth. -w: width of the raw pixel data in pixels. -h: height of the raw pixel data in pixels. -colortype: the color type of the raw input image. See explanation on PNG color types. -bitdepth: the bit depth of the raw input image. See explanation on PNG color types. -Return value: LodePNG error code (0 means no error). -*/ -unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth); - -/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/ -unsigned lodepng_encode32(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h); - -/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/ -unsigned lodepng_encode24(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h); - -#ifdef LODEPNG_COMPILE_DISK -/* -Converts raw pixel data into a PNG file on disk. -Same as the other encode functions, but instead takes a filename as output. - -NOTE: This overwrites existing files without warning! - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and encode in-memory.*/ -unsigned lodepng_encode_file(const char* filename, - const unsigned char* image, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth); - -/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image. - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and encode in-memory.*/ -unsigned lodepng_encode32_file(const char* filename, - const unsigned char* image, unsigned w, unsigned h); - -/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image. - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and encode in-memory.*/ -unsigned lodepng_encode24_file(const char* filename, - const unsigned char* image, unsigned w, unsigned h); -#endif /*LODEPNG_COMPILE_DISK*/ -#endif /*LODEPNG_COMPILE_ENCODER*/ - - -#ifdef LODEPNG_COMPILE_CPP -namespace lodepng { -#ifdef LODEPNG_COMPILE_DECODER -/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype -is the format to output the pixels to. Default is RGBA 8-bit per channel.*/ -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const unsigned char* in, size_t insize, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const std::vector& in, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -#ifdef LODEPNG_COMPILE_DISK -/* -Converts PNG file from disk to raw pixel data in memory. -Same as the other decode functions, but instead takes a filename as input. - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and decode in-memory. -*/ -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const std::string& filename, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -#endif /* LODEPNG_COMPILE_DISK */ -#endif /* LODEPNG_COMPILE_DECODER */ - -#ifdef LODEPNG_COMPILE_ENCODER -/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype -is that of the raw input data. The output PNG color type will be auto chosen.*/ -unsigned encode(std::vector& out, - const unsigned char* in, unsigned w, unsigned h, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -#ifdef LODEPNG_COMPILE_DISK -/* -Converts 32-bit RGBA raw pixel data into a PNG file on disk. -Same as the other encode functions, but instead takes a filename as output. - -NOTE: This overwrites existing files without warning! - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and decode in-memory. -*/ -unsigned encode(const std::string& filename, - const unsigned char* in, unsigned w, unsigned h, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -unsigned encode(const std::string& filename, - const std::vector& in, unsigned w, unsigned h, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -#endif /* LODEPNG_COMPILE_DISK */ -#endif /* LODEPNG_COMPILE_ENCODER */ -} /* namespace lodepng */ -#endif /*LODEPNG_COMPILE_CPP*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -#ifdef LODEPNG_COMPILE_ERROR_TEXT -/*Returns an English description of the numerical error code.*/ -const char* lodepng_error_text(unsigned code); -#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ - -#ifdef LODEPNG_COMPILE_DECODER -/*Settings for zlib decompression*/ -typedef struct LodePNGDecompressSettings LodePNGDecompressSettings; -struct LodePNGDecompressSettings { - /* Check LodePNGDecoderSettings for more ignorable errors such as ignore_crc */ - unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ - unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/ - - /*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding, - return an error, output a data size > max_output_size and all the data up to that point. This is - not hard limit nor a guarantee, but can prevent excessive memory usage. This setting is - ignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones. - Set to 0 to impose no limit (the default).*/ - size_t max_output_size; - - /*use custom zlib decoder instead of built in one (default: null). - Should return 0 if success, any non-0 if error (numeric value not exposed).*/ - unsigned (*custom_zlib)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGDecompressSettings*); - /*use custom deflate decoder instead of built in one (default: null) - if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate). - Should return 0 if success, any non-0 if error (numeric value not exposed).*/ - unsigned (*custom_inflate)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGDecompressSettings*); - - const void* custom_context; /*optional custom settings for custom functions*/ -}; - -extern const LodePNGDecompressSettings lodepng_default_decompress_settings; -void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings); -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER -/* -Settings for zlib compression. Tweaking these settings tweaks the balance -between speed and compression ratio. -*/ -typedef struct LodePNGCompressSettings LodePNGCompressSettings; -struct LodePNGCompressSettings /*deflate = compress*/ { - /*LZ77 related settings*/ - unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/ - unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/ - unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/ - unsigned minmatch; /*minimum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/ - unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/ - unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/ - - /*use custom zlib encoder instead of built in one (default: null)*/ - unsigned (*custom_zlib)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGCompressSettings*); - /*use custom deflate encoder instead of built in one (default: null) - if custom_zlib is used, custom_deflate is ignored since only the built in - zlib function will call custom_deflate*/ - unsigned (*custom_deflate)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGCompressSettings*); - - const void* custom_context; /*optional custom settings for custom functions*/ -}; - -extern const LodePNGCompressSettings lodepng_default_compress_settings; -void lodepng_compress_settings_init(LodePNGCompressSettings* settings); -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#ifdef LODEPNG_COMPILE_PNG -/* -Color mode of an image. Contains all information required to decode the pixel -bits to RGBA colors. This information is the same as used in the PNG file -format, and is used both for PNG and raw image data in LodePNG. -*/ -typedef struct LodePNGColorMode { - /*header (IHDR)*/ - LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/ - unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/ - - /* - palette (PLTE and tRNS) - - Dynamically allocated with the colors of the palette, including alpha. - This field may not be allocated directly, use lodepng_color_mode_init first, - then lodepng_palette_add per color to correctly initialize it (to ensure size - of exactly 1024 bytes). - - The alpha channels must be set as well, set them to 255 for opaque images. - - When decoding, with the default settings you can ignore this palette, since - LodePNG already fills the palette colors in the pixels of the raw RGBA output, - but when decoding to the original PNG color mode it is needed to reconstruct - the colors. - - The palette is only supported for color type 3. - */ - unsigned char* palette; /*palette in RGBARGBA... order. Must be either 0, or when allocated must have 1024 bytes*/ - size_t palettesize; /*palette size in number of colors (amount of used bytes is 4 * palettesize)*/ - - /* - transparent color key (tRNS) - - This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit. - For grayscale PNGs, r, g and b will all 3 be set to the same. - - When decoding, by default you can ignore this information, since LodePNG sets - pixels with this key to transparent already in the raw RGBA output. - - The color key is only supported for color types 0 and 2. - */ - unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/ - unsigned key_r; /*red/grayscale component of color key*/ - unsigned key_g; /*green component of color key*/ - unsigned key_b; /*blue component of color key*/ -} LodePNGColorMode; - -/*init, cleanup and copy functions to use with this struct*/ -void lodepng_color_mode_init(LodePNGColorMode* info); -void lodepng_color_mode_cleanup(LodePNGColorMode* info); -/*return value is error code (0 means no error)*/ -unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source); -/* Makes a temporary LodePNGColorMode that does not need cleanup (no palette) */ -LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth); - -void lodepng_palette_clear(LodePNGColorMode* info); -/*add 1 color to the palette*/ -unsigned lodepng_palette_add(LodePNGColorMode* info, - unsigned char r, unsigned char g, unsigned char b, unsigned char a); - -/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/ -unsigned lodepng_get_bpp(const LodePNGColorMode* info); -/*get the amount of color channels used, based on colortype in the struct. -If a palette is used, it counts as 1 channel.*/ -unsigned lodepng_get_channels(const LodePNGColorMode* info); -/*is it a grayscale type? (only colortype 0 or 4)*/ -unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info); -/*has it got an alpha channel? (only colortype 2 or 6)*/ -unsigned lodepng_is_alpha_type(const LodePNGColorMode* info); -/*has it got a palette? (only colortype 3)*/ -unsigned lodepng_is_palette_type(const LodePNGColorMode* info); -/*only returns true if there is a palette and there is a value in the palette with alpha < 255. -Loops through the palette to check this.*/ -unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info); -/* -Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image. -Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels). -Returns false if the image can only have opaque pixels. -In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values, -or if "key_defined" is true. -*/ -unsigned lodepng_can_have_alpha(const LodePNGColorMode* info); -/*Returns the byte size of a raw image buffer with given width, height and color mode*/ -size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color); - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -/*The information of a Time chunk in PNG.*/ -typedef struct LodePNGTime { - unsigned year; /*2 bytes used (0-65535)*/ - unsigned month; /*1-12*/ - unsigned day; /*1-31*/ - unsigned hour; /*0-23*/ - unsigned minute; /*0-59*/ - unsigned second; /*0-60 (to allow for leap seconds)*/ -} LodePNGTime; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -/*Information about the PNG image, except pixels, width and height.*/ -typedef struct LodePNGInfo { - /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/ - unsigned compression_method;/*compression method of the original file. Always 0.*/ - unsigned filter_method; /*filter method of the original file*/ - unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/ - LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/ - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /* - Suggested background color chunk (bKGD) - - This uses the same color mode and bit depth as the PNG (except no alpha channel), - with values truncated to the bit depth in the unsigned integer. - - For grayscale and palette PNGs, the value is stored in background_r. The values - in background_g and background_b are then unused. The decoder will set them - equal to background_r, the encoder ignores them in this case. - - When decoding, you may get these in a different color mode than the one you requested - for the raw pixels: the colortype and bitdepth defined by info_png.color, that is the - ones defined in the header of the PNG image, are used. - - When encoding with auto_convert, you must use the color model defined in info_png.color for - these values. The encoder normally ignores info_png.color when auto_convert is on, but will - use it to interpret these values (and convert copies of them to its chosen color model). - - When encoding, avoid setting this to an expensive color, such as a non-gray value - when the image is gray, or the compression will be worse since it will be forced to - write the PNG with a more expensive color mode (when auto_convert is on). - - The decoder does not use this background color to edit the color of pixels. This is a - completely optional metadata feature. - */ - unsigned background_defined; /*is a suggested background color given?*/ - unsigned background_r; /*red/gray/palette component of suggested background color*/ - unsigned background_g; /*green component of suggested background color*/ - unsigned background_b; /*blue component of suggested background color*/ - - /* - Non-international text chunks (tEXt and zTXt) - - The char** arrays each contain num strings. The actual messages are in - text_strings, while text_keys are keywords that give a short description what - the actual text represents, e.g. Title, Author, Description, or anything else. - - All the string fields below including strings, keys, names and language tags are null terminated. - The PNG specification uses null characters for the keys, names and tags, and forbids null - characters to appear in the main text which is why we can use null termination everywhere here. - - A keyword is minimum 1 character and maximum 79 characters long (plus the - additional null terminator). It's discouraged to use a single line length - longer than 79 characters for texts. - - Don't allocate these text buffers yourself. Use the init/cleanup functions - correctly and use lodepng_add_text and lodepng_clear_text. - - Standard text chunk keywords and strings are encoded using Latin-1. - */ - size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/ - char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/ - char** text_strings; /*the actual text*/ - - /* - International text chunks (iTXt) - Similar to the non-international text chunks, but with additional strings - "langtags" and "transkeys", and the following text encodings are used: - keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8. - keys must be 1-79 characters (plus the additional null terminator), the other - strings are any length. - */ - size_t itext_num; /*the amount of international texts in this PNG*/ - char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/ - char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/ - char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/ - char** itext_strings; /*the actual international text - UTF-8 string*/ - - /*time chunk (tIME)*/ - unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/ - LodePNGTime time; - - /*phys chunk (pHYs)*/ - unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/ - unsigned phys_x; /*pixels per unit in x direction*/ - unsigned phys_y; /*pixels per unit in y direction*/ - unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/ - - /* - Color profile related chunks: gAMA, cHRM, sRGB, iCPP, sBIT - - LodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these color - profile values. It merely passes on the information. If you wish to use color profiles and convert colors, please - use these values with a color management library. - - See the PNG, ICC and sRGB specifications for more information about the meaning of these values. - */ - - /* gAMA chunk: optional, overridden by sRGB or iCCP if those are present. */ - unsigned gama_defined; /* Whether a gAMA chunk is present (0 = not present, 1 = present). */ - unsigned gama_gamma; /* Gamma exponent times 100000 */ - - /* cHRM chunk: optional, overridden by sRGB or iCCP if those are present. */ - unsigned chrm_defined; /* Whether a cHRM chunk is present (0 = not present, 1 = present). */ - unsigned chrm_white_x; /* White Point x times 100000 */ - unsigned chrm_white_y; /* White Point y times 100000 */ - unsigned chrm_red_x; /* Red x times 100000 */ - unsigned chrm_red_y; /* Red y times 100000 */ - unsigned chrm_green_x; /* Green x times 100000 */ - unsigned chrm_green_y; /* Green y times 100000 */ - unsigned chrm_blue_x; /* Blue x times 100000 */ - unsigned chrm_blue_y; /* Blue y times 100000 */ - - /* - sRGB chunk: optional. May not appear at the same time as iCCP. - If gAMA is also present gAMA must contain value 45455. - If cHRM is also present cHRM must contain respectively 31270,32900,64000,33000,30000,60000,15000,6000. - */ - unsigned srgb_defined; /* Whether an sRGB chunk is present (0 = not present, 1 = present). */ - unsigned srgb_intent; /* Rendering intent: 0=perceptual, 1=rel. colorimetric, 2=saturation, 3=abs. colorimetric */ - - /* - iCCP chunk: optional. May not appear at the same time as sRGB. - - LodePNG does not parse or use the ICC profile (except its color space header field for an edge case), a - separate library to handle the ICC data (not included in LodePNG) format is needed to use it for color - management and conversions. - - For encoding, if iCCP is present, gAMA and cHRM are recommended to be added as well with values that match the ICC - profile as closely as possible, if you wish to do this you should provide the correct values for gAMA and cHRM and - enable their '_defined' flags since LodePNG will not automatically compute them from the ICC profile. - - For encoding, the ICC profile is required by the PNG specification to be an "RGB" profile for non-gray - PNG color types and a "GRAY" profile for gray PNG color types. If you disable auto_convert, you must ensure - the ICC profile type matches your requested color type, else the encoder gives an error. If auto_convert is - enabled (the default), and the ICC profile is not a good match for the pixel data, this will result in an encoder - error if the pixel data has non-gray pixels for a GRAY profile, or a silent less-optimal compression of the pixel - data if the pixels could be encoded as grayscale but the ICC profile is RGB. - - To avoid this do not set an ICC profile in the image unless there is a good reason for it, and when doing so - make sure you compute it carefully to avoid the above problems. - */ - unsigned iccp_defined; /* Whether an iCCP chunk is present (0 = not present, 1 = present). */ - char* iccp_name; /* Null terminated string with profile name, 1-79 bytes */ - /* - The ICC profile in iccp_profile_size bytes. - Don't allocate this buffer yourself. Use the init/cleanup functions - correctly and use lodepng_set_icc and lodepng_clear_icc. - */ - unsigned char* iccp_profile; - unsigned iccp_profile_size; /* The size of iccp_profile in bytes */ - - /* - sBIT chunk: significant bits. Optional metadata, only set this if needed. - - If defined, these values give the bit depth of the original data. Since PNG only stores 1, 2, 4, 8 or 16-bit - per channel data, the significant bits value can be used to indicate the original encoded data has another - sample depth, such as 10 or 12. - - Encoders using this value, when storing the pixel data, should use the most significant bits - of the data to store the original bits, and use a good sample depth scaling method such as - "left bit replication" to fill in the least significant bits, rather than fill zeroes. - - Decoders using this value, if able to work with data that's e.g. 10-bit or 12-bit, should right - shift the data to go back to the original bit depth, but decoders are also allowed to ignore - sbit and work e.g. with the 8-bit or 16-bit data from the PNG directly, since thanks - to the encoder contract, the values encoded in PNG are in valid range for the PNG bit depth. - - For grayscale images, sbit_g and sbit_b are not used, and for images that don't use color - type RGBA or grayscale+alpha, sbit_a is not used (it's not used even for palette images with - translucent palette values, or images with color key). The values that are used must be - greater than zero and smaller than or equal to the PNG bit depth. - - The color type from the header in the PNG image defines these used and unused fields: if - decoding with a color mode conversion, such as always decoding to RGBA, this metadata still - only uses the color type of the original PNG, and may e.g. lack the alpha channel info - if the PNG was RGB. When encoding with auto_convert (as well as without), also always the - color model defined in info_png.color determines this. - - NOTE: enabling sbit can hurt compression, because the encoder can then not always use - auto_convert to choose a more optimal color mode for the data, because the PNG format has - strict requirements for the allowed sbit values in combination with color modes. - For example, setting these fields to 10-bit will force the encoder to keep using a 16-bit per channel - color mode, even if the pixel data would in fact fit in a more efficient 8-bit mode. - */ - unsigned sbit_defined; /*is significant bits given? if not, the values below are unused*/ - unsigned sbit_r; /*red or gray component of significant bits*/ - unsigned sbit_g; /*green component of significant bits*/ - unsigned sbit_b; /*blue component of significant bits*/ - unsigned sbit_a; /*alpha component of significant bits*/ - - /* End of color profile related chunks */ - - - /* - unknown chunks: chunks not known by LodePNG, passed on byte for byte. - - There are 3 buffers, one for each position in the PNG where unknown chunks can appear. - Each buffer contains all unknown chunks for that position consecutively. - The 3 positions are: - 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND. - - For encoding, do not store critical chunks or known chunks that are enabled with a "_defined" flag - above in here, since the encoder will blindly follow this and could then encode an invalid PNG file - (such as one with two IHDR chunks or the disallowed combination of sRGB with iCCP). But do use - this if you wish to store an ancillary chunk that is not supported by LodePNG (such as sPLT or hIST), - or any non-standard PNG chunk. - - Do not allocate or traverse this data yourself. Use the chunk traversing functions declared - later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct. - */ - unsigned char* unknown_chunks_data[3]; - size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/ -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} LodePNGInfo; - -/*init, cleanup and copy functions to use with this struct*/ -void lodepng_info_init(LodePNGInfo* info); -void lodepng_info_cleanup(LodePNGInfo* info); -/*return value is error code (0 means no error)*/ -unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source); - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/ -void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ - -unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, - const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/ -void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/ - -/*replaces if exists*/ -unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size); -void lodepng_clear_icc(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -/* -Converts raw buffer from one color type to another color type, based on -LodePNGColorMode structs to describe the input and output color type. -See the reference manual at the end of this header file to see which color conversions are supported. -return value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported) -The out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel -of the output color type (lodepng_get_bpp). -For < 8 bpp images, there should not be padding bits at the end of scanlines. -For 16-bit per channel colors, uses big endian format like PNG does. -Return value is LodePNG error code -*/ -unsigned lodepng_convert(unsigned char* out, const unsigned char* in, - const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, - unsigned w, unsigned h); - -#ifdef LODEPNG_COMPILE_DECODER -/* -Settings for the decoder. This contains settings for the PNG and the Zlib -decoder, but not the Info settings from the Info structs. -*/ -typedef struct LodePNGDecoderSettings { - LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ - - /* Check LodePNGDecompressSettings for more ignorable errors such as ignore_adler32 */ - unsigned ignore_crc; /*ignore CRC checksums*/ - unsigned ignore_critical; /*ignore unknown critical chunks*/ - unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/ - /* TODO: make a system involving warnings with levels and a strict mode instead. Other potentially recoverable - errors: srgb rendering intent value, size of content of ancillary chunks, more than 79 characters for some - strings, placement/combination rules for ancillary chunks, crc of unknown chunks, allowed characters - in string keys, etc... */ - - unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/ - - /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/ - unsigned remember_unknown_chunks; - - /* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned, - unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size. - By default it is a value that prevents unreasonably large strings from hogging memory. */ - size_t max_text_size; - - /* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to - 0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than any - legitimate profile could be to hog memory. */ - size_t max_icc_size; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} LodePNGDecoderSettings; - -void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings); -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER -/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/ -typedef enum LodePNGFilterStrategy { - /*every filter at zero*/ - LFS_ZERO = 0, - /*every filter at 1, 2, 3 or 4 (paeth), unlike LFS_ZERO not a good choice, but for testing*/ - LFS_ONE = 1, - LFS_TWO = 2, - LFS_THREE = 3, - LFS_FOUR = 4, - /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/ - LFS_MINSUM, - /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending - on the image, this is better or worse than minsum.*/ - LFS_ENTROPY, - /* - Brute-force-search PNG filters by compressing each filter for each scanline. - Experimental, very slow, and only rarely gives better compression than MINSUM. - */ - LFS_BRUTE_FORCE, - /*use predefined_filters buffer: you specify the filter type for each scanline*/ - LFS_PREDEFINED -} LodePNGFilterStrategy; - -/*Gives characteristics about the integer RGBA colors of the image (count, alpha channel usage, bit depth, ...), -which helps decide which color model to use for encoding. -Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms.*/ -typedef struct LodePNGColorStats { - unsigned colored; /*not grayscale*/ - unsigned key; /*image is not opaque and color key is possible instead of full alpha*/ - unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/ - unsigned short key_g; - unsigned short key_b; - unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/ - unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16 or allow_palette is disabled.*/ - unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order, only valid when numcolors is valid*/ - unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for grayscale only. 16 if 16-bit per channel required.*/ - size_t numpixels; - - /*user settings for computing/using the stats*/ - unsigned allow_palette; /*default 1. if 0, disallow choosing palette colortype in auto_choose_color, and don't count numcolors*/ - unsigned allow_greyscale; /*default 1. if 0, choose RGB or RGBA even if the image only has gray colors*/ -} LodePNGColorStats; - -void lodepng_color_stats_init(LodePNGColorStats* stats); - -/*Get a LodePNGColorStats of the image. The stats must already have been inited. -Returns error code (e.g. alloc fail) or 0 if ok.*/ -unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, - const unsigned char* image, unsigned w, unsigned h, - const LodePNGColorMode* mode_in); - -/*Settings for the encoder.*/ -typedef struct LodePNGEncoderSettings { - LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ - - unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/ - - /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than - 8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to - completely follow the official PNG heuristic, filter_palette_zero must be true and - filter_strategy must be LFS_MINSUM*/ - unsigned filter_palette_zero; - /*Which filter strategy to use when not using zeroes due to filter_palette_zero. - Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/ - LodePNGFilterStrategy filter_strategy; - /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with - the same length as the amount of scanlines in the image, and each value must <= 5. You - have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero - must be set to 0 to ensure this is also used on palette or low bitdepth images.*/ - const unsigned char* predefined_filters; - - /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). - If colortype is 3, PLTE is always created. If color type is explicitely set - to a grayscale type (1 or 4), this is not done and is ignored. If enabling this, - a palette must be present in the info_png. - NOTE: enabling this may worsen compression if auto_convert is used to choose - optimal color mode, because it cannot use grayscale color modes in this case*/ - unsigned force_palette; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*add LodePNG identifier and version as a text chunk, for debugging*/ - unsigned add_id; - /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/ - unsigned text_compression; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} LodePNGEncoderSettings; - -void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings); -#endif /*LODEPNG_COMPILE_ENCODER*/ - - -#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) -/*The settings, state and information for extended encoding and decoding.*/ -typedef struct LodePNGState { -#ifdef LODEPNG_COMPILE_DECODER - LodePNGDecoderSettings decoder; /*the decoding settings*/ -#endif /*LODEPNG_COMPILE_DECODER*/ -#ifdef LODEPNG_COMPILE_ENCODER - LodePNGEncoderSettings encoder; /*the encoding settings*/ -#endif /*LODEPNG_COMPILE_ENCODER*/ - LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/ - LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/ - unsigned error; -} LodePNGState; - -/*init, cleanup and copy functions to use with this struct*/ -void lodepng_state_init(LodePNGState* state); -void lodepng_state_cleanup(LodePNGState* state); -void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source); -#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ - -#ifdef LODEPNG_COMPILE_DECODER -/* -Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and -getting much more information about the PNG image and color mode. -*/ -unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize); - -/* -Read the PNG header, but not the actual data. This returns only the information -that is in the IHDR chunk of the PNG, such as width, height and color type. The -information is placed in the info_png field of the LodePNGState. -*/ -unsigned lodepng_inspect(unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize); -#endif /*LODEPNG_COMPILE_DECODER*/ - -/* -Reads one metadata chunk (other than IHDR, which is handled by lodepng_inspect) -of the PNG file and outputs what it read in the state. Returns error code on failure. -Use lodepng_inspect first with a new state, then e.g. lodepng_chunk_find_const -to find the desired chunk type, and if non null use lodepng_inspect_chunk (with -chunk_pointer - start_of_file as pos). -Supports most metadata chunks from the PNG standard (gAMA, bKGD, tEXt, ...). -Ignores unsupported, unknown, non-metadata or IHDR chunks (without error). -Requirements: &in[pos] must point to start of a chunk, must use regular -lodepng_inspect first since format of most other chunks depends on IHDR, and if -there is a PLTE chunk, that one must be inspected before tRNS or bKGD. -*/ -unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, - const unsigned char* in, size_t insize); - -#ifdef LODEPNG_COMPILE_ENCODER -/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/ -unsigned lodepng_encode(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h, - LodePNGState* state); -#endif /*LODEPNG_COMPILE_ENCODER*/ - -/* -The lodepng_chunk functions are normally not needed, except to traverse the -unknown chunks stored in the LodePNGInfo struct, or add new ones to it. -It also allows traversing the chunks of an encoded PNG file yourself. - -The chunk pointer always points to the beginning of the chunk itself, that is -the first byte of the 4 length bytes. - -In the PNG file format, chunks have the following format: --4 bytes length: length of the data of the chunk in bytes (chunk itself is 12 bytes longer) --4 bytes chunk type (ASCII a-z,A-Z only, see below) --length bytes of data (may be 0 bytes if length was 0) --4 bytes of CRC, computed on chunk name + data - -The first chunk starts at the 8th byte of the PNG file, the entire rest of the file -exists out of concatenated chunks with the above format. - -PNG standard chunk ASCII naming conventions: --First byte: uppercase = critical, lowercase = ancillary --Second byte: uppercase = public, lowercase = private --Third byte: must be uppercase --Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy -*/ - -/* -Gets the length of the data of the chunk. Total chunk length has 12 bytes more. -There must be at least 4 bytes to read from. If the result value is too large, -it may be corrupt data. -*/ -unsigned lodepng_chunk_length(const unsigned char* chunk); - -/*puts the 4-byte type in null terminated string*/ -void lodepng_chunk_type(char type[5], const unsigned char* chunk); - -/*check if the type is the given type*/ -unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type); - -/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/ -unsigned char lodepng_chunk_ancillary(const unsigned char* chunk); - -/*0: public, 1: private (see PNG standard)*/ -unsigned char lodepng_chunk_private(const unsigned char* chunk); - -/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/ -unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk); - -/*get pointer to the data of the chunk, where the input points to the header of the chunk*/ -unsigned char* lodepng_chunk_data(unsigned char* chunk); -const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk); - -/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/ -unsigned lodepng_chunk_check_crc(const unsigned char* chunk); - -/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ -void lodepng_chunk_generate_crc(unsigned char* chunk); - -/* -Iterate to next chunks, allows iterating through all chunks of the PNG file. -Input must be at the beginning of a chunk (result of a previous lodepng_chunk_next call, -or the 8th byte of a PNG file which always has the first chunk), or alternatively may -point to the first byte of the PNG file (which is not a chunk but the magic header, the -function will then skip over it and return the first real chunk). -Will output pointer to the start of the next chunk, or at or beyond end of the file if there -is no more chunk after this or possibly if the chunk is corrupt. -Start this process at the 8th byte of the PNG file. -In a non-corrupt PNG file, the last chunk should have name "IEND". -*/ -unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end); -const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end); - -/*Finds the first chunk with the given type in the range [chunk, end), or returns NULL if not found.*/ -unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]); -const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]); - -/* -Appends chunk to the data in out. The given chunk should already have its chunk header. -The out variable and outsize are updated to reflect the new reallocated buffer. -Returns error code (0 if it went ok) -*/ -unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk); - -/* -Appends new chunk to out. The chunk to append is given by giving its length, type -and data separately. The type is a 4-letter string. -The out variable and outsize are updated to reflect the new reallocated buffer. -Returne error code (0 if it went ok) -*/ -unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, unsigned length, - const char* type, const unsigned char* data); - - -/*Calculate CRC32 of buffer*/ -unsigned lodepng_crc32(const unsigned char* buf, size_t len); -#endif /*LODEPNG_COMPILE_PNG*/ - - -#ifdef LODEPNG_COMPILE_ZLIB -/* -This zlib part can be used independently to zlib compress and decompress a -buffer. It cannot be used to create gzip files however, and it only supports the -part of zlib that is required for PNG, it does not support dictionaries. -*/ - -#ifdef LODEPNG_COMPILE_DECODER -/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/ -unsigned lodepng_inflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings); - -/* -Decompresses Zlib data. Reallocates the out buffer and appends the data. The -data must be according to the zlib specification. -Either, *out must be NULL and *outsize must be 0, or, *out must be a valid -buffer and *outsize its size in bytes. out must be freed by user after usage. -*/ -unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings); -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER -/* -Compresses data with Zlib. Reallocates the out buffer and appends the data. -Zlib adds a small header and trailer around the deflate data. -The data is output in the format of the zlib specification. -Either, *out must be NULL and *outsize must be 0, or, *out must be a valid -buffer and *outsize its size in bytes. out must be freed by user after usage. -*/ -unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings); - -/* -Find length-limited Huffman code for given frequencies. This function is in the -public interface only for tests, it's used internally by lodepng_deflate. -*/ -unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, - size_t numcodes, unsigned maxbitlen); - -/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/ -unsigned lodepng_deflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings); - -#endif /*LODEPNG_COMPILE_ENCODER*/ -#endif /*LODEPNG_COMPILE_ZLIB*/ - -#ifdef LODEPNG_COMPILE_DISK -/* -Load a file from disk into buffer. The function allocates the out buffer, and -after usage you should free it. -out: output parameter, contains pointer to loaded buffer. -outsize: output parameter, size of the allocated out buffer -filename: the path to the file to load -return value: error code (0 means ok) - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and decode in-memory. -*/ -unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename); - -/* -Save a file from buffer to disk. Warning, if it exists, this function overwrites -the file without warning! -buffer: the buffer to write -buffersize: size of the buffer to write -filename: the path to the file to save to -return value: error code (0 means ok) - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and encode in-memory -*/ -unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename); -#endif /*LODEPNG_COMPILE_DISK*/ - -#ifdef LODEPNG_COMPILE_CPP -/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */ -namespace lodepng { -#ifdef LODEPNG_COMPILE_PNG -class State : public LodePNGState { - public: - State(); - State(const State& other); - ~State(); - State& operator=(const State& other); -}; - -#ifdef LODEPNG_COMPILE_DECODER -/* Same as other lodepng::decode, but using a State for more settings and information. */ -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const unsigned char* in, size_t insize); -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const std::vector& in); -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER -/* Same as other lodepng::encode, but using a State for more settings and information. */ -unsigned encode(std::vector& out, - const unsigned char* in, unsigned w, unsigned h, - State& state); -unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - State& state); -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#ifdef LODEPNG_COMPILE_DISK -/* -Load a file from disk into an std::vector. -return value: error code (0 means ok) - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and decode in-memory -*/ -unsigned load_file(std::vector& buffer, const std::string& filename); - -/* -Save the binary data in an std::vector to a file on disk. The file is overwritten -without warning. - -NOTE: Wide-character filenames are not supported, you can use an external method -to handle such files and encode in-memory -*/ -unsigned save_file(const std::vector& buffer, const std::string& filename); -#endif /* LODEPNG_COMPILE_DISK */ -#endif /* LODEPNG_COMPILE_PNG */ - -#ifdef LODEPNG_COMPILE_ZLIB -#ifdef LODEPNG_COMPILE_DECODER -/* Zlib-decompress an unsigned char buffer */ -unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); - -/* Zlib-decompress an std::vector */ -unsigned decompress(std::vector& out, const std::vector& in, - const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); -#endif /* LODEPNG_COMPILE_DECODER */ - -#ifdef LODEPNG_COMPILE_ENCODER -/* Zlib-compress an unsigned char buffer */ -unsigned compress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGCompressSettings& settings = lodepng_default_compress_settings); - -/* Zlib-compress an std::vector */ -unsigned compress(std::vector& out, const std::vector& in, - const LodePNGCompressSettings& settings = lodepng_default_compress_settings); -#endif /* LODEPNG_COMPILE_ENCODER */ -#endif /* LODEPNG_COMPILE_ZLIB */ -} /* namespace lodepng */ -#endif /*LODEPNG_COMPILE_CPP*/ - -/* -TODO: -[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often -[.] check compatibility with various compilers - done but needs to be redone for every newer version -[X] converting color to 16-bit per channel types -[X] support color profile chunk types (but never let them touch RGB values by default) -[ ] support all public PNG chunk types (almost done except sPLT and hIST) -[ ] make sure encoder generates no chunks with size > (2^31)-1 -[ ] partial decoding (stream processing) -[X] let the "isFullyOpaque" function check color keys and transparent palettes too -[X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl" -[ ] allow treating some errors like warnings, when image is recoverable (e.g. 69, 57, 58) -[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ... -[ ] error messages with line numbers (and version) -[ ] errors in state instead of as return code? -[ ] new errors/warnings like suspiciously big decompressed ztxt or iccp chunk -[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes -[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ... -[ ] allow user to give data (void*) to custom allocator -[X] provide alternatives for C library functions not present on some platforms (memcpy, ...) -*/ - -#endif /*LODEPNG_H inclusion guard*/ - -/* -LodePNG Documentation ---------------------- - -0. table of contents --------------------- - - 1. about - 1.1. supported features - 1.2. features not supported - 2. C and C++ version - 3. security - 4. decoding - 5. encoding - 6. color conversions - 6.1. PNG color types - 6.2. color conversions - 6.3. padding bits - 6.4. A note about 16-bits per channel and endianness - 7. error values - 8. chunks and PNG editing - 9. compiler support - 10. examples - 10.1. decoder C++ example - 10.2. decoder C example - 11. state settings reference - 12. changes - 13. contact information - - -1. about --------- - -PNG is a file format to store raster images losslessly with good compression, -supporting different color types and alpha channel. - -LodePNG is a PNG codec according to the Portable Network Graphics (PNG) -Specification (Second Edition) - W3C Recommendation 10 November 2003. - -The specifications used are: - -*) Portable Network Graphics (PNG) Specification (Second Edition): - http://www.w3.org/TR/2003/REC-PNG-20031110 -*) RFC 1950 ZLIB Compressed Data Format version 3.3: - http://www.gzip.org/zlib/rfc-zlib.html -*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3: - http://www.gzip.org/zlib/rfc-deflate.html - -The most recent version of LodePNG can currently be found at -http://lodev.org/lodepng/ - -LodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds -extra functionality. - -LodePNG exists out of two files: --lodepng.h: the header file for both C and C++ --lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage - -If you want to start using LodePNG right away without reading this doc, get the -examples from the LodePNG website to see how to use it in code, or check the -smaller examples in chapter 13 here. - -LodePNG is simple but only supports the basic requirements. To achieve -simplicity, the following design choices were made: There are no dependencies -on any external library. There are functions to decode and encode a PNG with -a single function call, and extended versions of these functions taking a -LodePNGState struct allowing to specify or get more information. By default -the colors of the raw image are always RGB or RGBA, no matter what color type -the PNG file uses. To read and write files, there are simple functions to -convert the files to/from buffers in memory. - -This all makes LodePNG suitable for loading textures in games, demos and small -programs, ... It's less suitable for full fledged image editors, loading PNGs -over network (it requires all the image data to be available before decoding can -begin), life-critical systems, ... - -1.1. supported features ------------------------ - -The following features are supported by the decoder: - -*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image, - or the same color type as the PNG -*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image -*) Adam7 interlace and deinterlace for any color type -*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk -*) support for alpha channels, including RGBA color model, translucent palettes and color keying -*) zlib decompression (inflate) -*) zlib compression (deflate) -*) CRC32 and ADLER32 checksums -*) colorimetric color profile conversions: currently experimentally available in lodepng_util.cpp only, - plus alternatively ability to pass on chroma/gamma/ICC profile information to other color management system. -*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks. -*) the following chunks are supported by both encoder and decoder: - IHDR: header information - PLTE: color palette - IDAT: pixel data - IEND: the final chunk - tRNS: transparency for palettized images - tEXt: textual information - zTXt: compressed textual information - iTXt: international textual information - bKGD: suggested background color - pHYs: physical dimensions - tIME: modification time - cHRM: RGB chromaticities - gAMA: RGB gamma correction - iCCP: ICC color profile - sRGB: rendering intent - sBIT: significant bits - -1.2. features not supported ---------------------------- - -The following features are not (yet) supported: - -*) some features needed to make a conformant PNG-Editor might be still missing. -*) partial loading/stream processing. All data must be available and is processed in one call. -*) The hIST and sPLT public chunks are not (yet) supported but treated as unknown chunks - - -2. C and C++ version --------------------- - -The C version uses buffers allocated with alloc that you need to free() -yourself. You need to use init and cleanup functions for each struct whenever -using a struct from the C version to avoid exploits and memory leaks. - -The C++ version has extra functions with std::vectors in the interface and the -lodepng::State class which is a LodePNGState with constructor and destructor. - -These files work without modification for both C and C++ compilers because all -the additional C++ code is in "#ifdef __cplusplus" blocks that make C-compilers -ignore it, and the C code is made to compile both with strict ISO C90 and C++. - -To use the C++ version, you need to rename the source file to lodepng.cpp -(instead of lodepng.c), and compile it with a C++ compiler. - -To use the C version, you need to rename the source file to lodepng.c (instead -of lodepng.cpp), and compile it with a C compiler. - - -3. Security ------------ - -Even if carefully designed, it's always possible that LodePNG contains possible -exploits. If you discover one, please let me know, and it will be fixed. - -When using LodePNG, care has to be taken with the C version of LodePNG, as well -as the C-style structs when working with C++. The following conventions are used -for all C-style structs: - --if a struct has a corresponding init function, always call the init function when making a new one --if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks --if a struct has a corresponding copy function, use the copy function instead of "=". - The destination must also be inited already. - - -4. Decoding ------------ - -Decoding converts a PNG compressed image to a raw pixel buffer. - -Most documentation on using the decoder is at its declarations in the header -above. For C, simple decoding can be done with functions such as -lodepng_decode32, and more advanced decoding can be done with the struct -LodePNGState and lodepng_decode. For C++, all decoding can be done with the -various lodepng::decode functions, and lodepng::State can be used for advanced -features. - -When using the LodePNGState, it uses the following fields for decoding: -*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here -*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get -*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use - -LodePNGInfo info_png --------------------- - -After decoding, this contains extra information of the PNG image, except the actual -pixels, width and height because these are already gotten directly from the decoder -functions. - -It contains for example the original color type of the PNG image, text comments, -suggested background color, etc... More details about the LodePNGInfo struct are -at its declaration documentation. - -LodePNGColorMode info_raw -------------------------- - -When decoding, here you can specify which color type you want -the resulting raw image to be. If this is different from the colortype of the -PNG, then the decoder will automatically convert the result. This conversion -always works, except if you want it to convert a color PNG to grayscale or to -a palette with missing colors. - -By default, 32-bit color is used for the result. - -LodePNGDecoderSettings decoder ------------------------------- - -The settings can be used to ignore the errors created by invalid CRC and Adler32 -chunks, and to disable the decoding of tEXt chunks. - -There's also a setting color_convert, true by default. If false, no conversion -is done, the resulting data will be as it was in the PNG (after decompression) -and you'll have to puzzle the colors of the pixels together yourself using the -color type information in the LodePNGInfo. - - -5. Encoding ------------ - -Encoding converts a raw pixel buffer to a PNG compressed image. - -Most documentation on using the encoder is at its declarations in the header -above. For C, simple encoding can be done with functions such as -lodepng_encode32, and more advanced decoding can be done with the struct -LodePNGState and lodepng_encode. For C++, all encoding can be done with the -various lodepng::encode functions, and lodepng::State can be used for advanced -features. - -Like the decoder, the encoder can also give errors. However it gives less errors -since the encoder input is trusted, the decoder input (a PNG image that could -be forged by anyone) is not trusted. - -When using the LodePNGState, it uses the following fields for encoding: -*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be. -*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has -*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use - -LodePNGInfo info_png --------------------- - -When encoding, you use this the opposite way as when decoding: for encoding, -you fill in the values you want the PNG to have before encoding. By default it's -not needed to specify a color type for the PNG since it's automatically chosen, -but it's possible to choose it yourself given the right settings. - -The encoder will not always exactly match the LodePNGInfo struct you give, -it tries as close as possible. Some things are ignored by the encoder. The -encoder uses, for example, the following settings from it when applicable: -colortype and bitdepth, text chunks, time chunk, the color key, the palette, the -background color, the interlace method, unknown chunks, ... - -When encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk. -If the palette contains any colors for which the alpha channel is not 255 (so -there are translucent colors in the palette), it'll add a tRNS chunk. - -LodePNGColorMode info_raw -------------------------- - -You specify the color type of the raw image that you give to the input here, -including a possible transparent color key and palette you happen to be using in -your raw image data. - -By default, 32-bit color is assumed, meaning your input has to be in RGBA -format with 4 bytes (unsigned chars) per pixel. - -LodePNGEncoderSettings encoder ------------------------------- - -The following settings are supported (some are in sub-structs): -*) auto_convert: when this option is enabled, the encoder will -automatically choose the smallest possible color mode (including color key) that -can encode the colors of all pixels without information loss. -*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree, - 2 = dynamic huffman tree (best compression). Should be 2 for proper - compression. -*) use_lz77: whether or not to use LZ77 for compressed block types. Should be - true for proper compression. -*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value - 2048 by default, but can be set to 32768 for better, but slow, compression. -*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE - chunk if force_palette is true. This can used as suggested palette to convert - to by viewers that don't support more than 256 colors (if those still exist) -*) add_id: add text chunk "Encoder: LodePNG " to the image. -*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks. - zTXt chunks use zlib compression on the text. This gives a smaller result on - large texts but a larger result on small texts (such as a single program name). - It's all tEXt or all zTXt though, there's no separate setting per text yet. - - -6. color conversions --------------------- - -An important thing to note about LodePNG, is that the color type of the PNG, and -the color type of the raw image, are completely independent. By default, when -you decode a PNG, you get the result as a raw image in the color type you want, -no matter whether the PNG was encoded with a palette, grayscale or RGBA color. -And if you encode an image, by default LodePNG will automatically choose the PNG -color type that gives good compression based on the values of colors and amount -of colors in the image. It can be configured to let you control it instead as -well, though. - -To be able to do this, LodePNG does conversions from one color mode to another. -It can convert from almost any color type to any other color type, except the -following conversions: RGB to grayscale is not supported, and converting to a -palette when the palette doesn't have a required color is not supported. This is -not supported on purpose: this is information loss which requires a color -reduction algorithm that is beyond the scope of a PNG encoder (yes, RGB to gray -is easy, but there are multiple ways if you want to give some channels more -weight). - -By default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB -color, no matter what color type the PNG has. And by default when encoding, -LodePNG automatically picks the best color model for the output PNG, and expects -the input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control -the color format of the images yourself, you can skip this chapter. - -6.1. PNG color types --------------------- - -A PNG image can have many color types, ranging from 1-bit color to 64-bit color, -as well as palettized color modes. After the zlib decompression and unfiltering -in the PNG image is done, the raw pixel data will have that color type and thus -a certain amount of bits per pixel. If you want the output raw image after -decoding to have another color type, a conversion is done by LodePNG. - -The PNG specification gives the following color types: - -0: grayscale, bit depths 1, 2, 4, 8, 16 -2: RGB, bit depths 8 and 16 -3: palette, bit depths 1, 2, 4 and 8 -4: grayscale with alpha, bit depths 8 and 16 -6: RGBA, bit depths 8 and 16 - -Bit depth is the amount of bits per pixel per color channel. So the total amount -of bits per pixel is: amount of channels * bitdepth. - -6.2. color conversions ----------------------- - -As explained in the sections about the encoder and decoder, you can specify -color types and bit depths in info_png and info_raw to change the default -behaviour. - -If, when decoding, you want the raw image to be something else than the default, -you need to set the color type and bit depth you want in the LodePNGColorMode, -or the parameters colortype and bitdepth of the simple decoding function. - -If, when encoding, you use another color type than the default in the raw input -image, you need to specify its color type and bit depth in the LodePNGColorMode -of the raw image, or use the parameters colortype and bitdepth of the simple -encoding function. - -If, when encoding, you don't want LodePNG to choose the output PNG color type -but control it yourself, you need to set auto_convert in the encoder settings -to false, and specify the color type you want in the LodePNGInfo of the -encoder (including palette: it can generate a palette if auto_convert is true, -otherwise not). - -If the input and output color type differ (whether user chosen or auto chosen), -LodePNG will do a color conversion, which follows the rules below, and may -sometimes result in an error. - -To avoid some confusion: --the decoder converts from PNG to raw image --the encoder converts from raw image to PNG --the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image --the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG --when encoding, the color type in LodePNGInfo is ignored if auto_convert - is enabled, it is automatically generated instead --when decoding, the color type in LodePNGInfo is set by the decoder to that of the original - PNG image, but it can be ignored since the raw image has the color type you requested instead --if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion - between the color types is done if the color types are supported. If it is not - supported, an error is returned. If the types are the same, no conversion is done. --even though some conversions aren't supported, LodePNG supports loading PNGs from any - colortype and saving PNGs to any colortype, sometimes it just requires preparing - the raw image correctly before encoding. --both encoder and decoder use the same color converter. - -The function lodepng_convert does the color conversion. It is available in the -interface but normally isn't needed since the encoder and decoder already call -it. - -Non supported color conversions: --color to grayscale when non-gray pixels are present: no error is thrown, but -the result will look ugly because only the red channel is taken (it assumes all -three channels are the same in this case so ignores green and blue). The reason -no error is given is to allow converting from three-channel grayscale images to -one-channel even if there are numerical imprecisions. --anything to palette when the palette does not have an exact match for a from-color -in it: in this case an error is thrown - -Supported color conversions: --anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA --any gray or gray+alpha, to gray or gray+alpha --anything to a palette, as long as the palette has the requested colors in it --removing alpha channel --higher to smaller bitdepth, and vice versa - -If you want no color conversion to be done (e.g. for speed or control): --In the encoder, you can make it save a PNG with any color type by giving the -raw color mode and LodePNGInfo the same color mode, and setting auto_convert to -false. --In the decoder, you can make it store the pixel data in the same color type -as the PNG has, by setting the color_convert setting to false. Settings in -info_raw are then ignored. - -6.3. padding bits ------------------ - -In the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines -have a bit amount that isn't a multiple of 8, then padding bits are used so that each -scanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output. -The raw input image you give to the encoder, and the raw output image you get from the decoder -will NOT have these padding bits, e.g. in the case of a 1-bit image with a width -of 7 pixels, the first pixel of the second scanline will the 8th bit of the first byte, -not the first bit of a new byte. - -6.4. A note about 16-bits per channel and endianness ----------------------------------------------------- - -LodePNG uses unsigned char arrays for 16-bit per channel colors too, just like -for any other color format. The 16-bit values are stored in big endian (most -significant byte first) in these arrays. This is the opposite order of the -little endian used by x86 CPU's. - -LodePNG always uses big endian because the PNG file format does so internally. -Conversions to other formats than PNG uses internally are not supported by -LodePNG on purpose, there are myriads of formats, including endianness of 16-bit -colors, the order in which you store R, G, B and A, and so on. Supporting and -converting to/from all that is outside the scope of LodePNG. - -This may mean that, depending on your use case, you may want to convert the big -endian output of LodePNG to little endian with a for loop. This is certainly not -always needed, many applications and libraries support big endian 16-bit colors -anyway, but it means you cannot simply cast the unsigned char* buffer to an -unsigned short* buffer on x86 CPUs. - - -7. error values ---------------- - -All functions in LodePNG that return an error code, return 0 if everything went -OK, or a non-zero code if there was an error. - -The meaning of the LodePNG error values can be retrieved with the function -lodepng_error_text: given the numerical error code, it returns a description -of the error in English as a string. - -Check the implementation of lodepng_error_text to see the meaning of each code. - -It is not recommended to use the numerical values to programmatically make -different decisions based on error types as the numbers are not guaranteed to -stay backwards compatible. They are for human consumption only. Programmatically -only 0 or non-0 matter. - - -8. chunks and PNG editing -------------------------- - -If you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG -editor that should follow the rules about handling of unknown chunks, or if your -program is able to read other types of chunks than the ones handled by LodePNG, -then that's possible with the chunk functions of LodePNG. - -A PNG chunk has the following layout: - -4 bytes length -4 bytes type name -length bytes data -4 bytes CRC - -8.1. iterating through chunks ------------------------------ - -If you have a buffer containing the PNG image data, then the first chunk (the -IHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the -signature of the PNG and are not part of a chunk. But if you start at byte 8 -then you have a chunk, and can check the following things of it. - -NOTE: none of these functions check for memory buffer boundaries. To avoid -exploits, always make sure the buffer contains all the data of the chunks. -When using lodepng_chunk_next, make sure the returned value is within the -allocated memory. - -unsigned lodepng_chunk_length(const unsigned char* chunk): - -Get the length of the chunk's data. The total chunk length is this length + 12. - -void lodepng_chunk_type(char type[5], const unsigned char* chunk): -unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type): - -Get the type of the chunk or compare if it's a certain type - -unsigned char lodepng_chunk_critical(const unsigned char* chunk): -unsigned char lodepng_chunk_private(const unsigned char* chunk): -unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk): - -Check if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are). -Check if the chunk is private (public chunks are part of the standard, private ones not). -Check if the chunk is safe to copy. If it's not, then, when modifying data in a critical -chunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your -program doesn't handle that type of unknown chunk. - -unsigned char* lodepng_chunk_data(unsigned char* chunk): -const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk): - -Get a pointer to the start of the data of the chunk. - -unsigned lodepng_chunk_check_crc(const unsigned char* chunk): -void lodepng_chunk_generate_crc(unsigned char* chunk): - -Check if the crc is correct or generate a correct one. - -unsigned char* lodepng_chunk_next(unsigned char* chunk): -const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk): - -Iterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these -functions do no boundary checking of the allocated data whatsoever, so make sure there is enough -data available in the buffer to be able to go to the next chunk. - -unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk): -unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, unsigned length, - const char* type, const unsigned char* data): - -These functions are used to create new chunks that are appended to the data in *out that has -length *outsize. The append function appends an existing chunk to the new data. The create -function creates a new chunk with the given parameters and appends it. Type is the 4-letter -name of the chunk. - -8.2. chunks in info_png ------------------------ - -The LodePNGInfo struct contains fields with the unknown chunk in it. It has 3 -buffers (each with size) to contain 3 types of unknown chunks: -the ones that come before the PLTE chunk, the ones that come between the PLTE -and the IDAT chunks, and the ones that come after the IDAT chunks. -It's necessary to make the distinction between these 3 cases because the PNG -standard forces to keep the ordering of unknown chunks compared to the critical -chunks, but does not force any other ordering rules. - -info_png.unknown_chunks_data[0] is the chunks before PLTE -info_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT -info_png.unknown_chunks_data[2] is the chunks after IDAT - -The chunks in these 3 buffers can be iterated through and read by using the same -way described in the previous subchapter. - -When using the decoder to decode a PNG, you can make it store all unknown chunks -if you set the option settings.remember_unknown_chunks to 1. By default, this -option is off (0). - -The encoder will always encode unknown chunks that are stored in the info_png. -If you need it to add a particular chunk that isn't known by LodePNG, you can -use lodepng_chunk_append or lodepng_chunk_create to the chunk data in -info_png.unknown_chunks_data[x]. - -Chunks that are known by LodePNG should not be added in that way. E.g. to make -LodePNG add a bKGD chunk, set background_defined to true and add the correct -parameters there instead. - - -9. compiler support -------------------- - -No libraries other than the current standard C library are needed to compile -LodePNG. For the C++ version, only the standard C++ library is needed on top. -Add the files lodepng.c(pp) and lodepng.h to your project, include -lodepng.h where needed, and your program can read/write PNG files. - -It is compatible with C90 and up, and C++03 and up. - -If performance is important, use optimization when compiling! For both the -encoder and decoder, this makes a large difference. - -Make sure that LodePNG is compiled with the same compiler of the same version -and with the same settings as the rest of the program, or the interfaces with -std::vectors and std::strings in C++ can be incompatible. - -CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets. - -*) gcc and g++ - -LodePNG is developed in gcc so this compiler is natively supported. It gives no -warnings with compiler options "-Wall -Wextra -pedantic -ansi", with gcc and g++ -version 4.7.1 on Linux, 32-bit and 64-bit. - -*) Clang - -Fully supported and warning-free. - -*) Mingw - -The Mingw compiler (a port of gcc for Windows) should be fully supported by -LodePNG. - -*) Visual Studio and Visual C++ Express Edition - -LodePNG should be warning-free with warning level W4. Two warnings were disabled -with pragmas though: warning 4244 about implicit conversions, and warning 4996 -where it wants to use a non-standard function fopen_s instead of the standard C -fopen. - -Visual Studio may want "stdafx.h" files to be included in each source file and -give an error "unexpected end of file while looking for precompiled header". -This is not standard C++ and will not be added to the stock LodePNG. You can -disable it for lodepng.cpp only by right clicking it, Properties, C/C++, -Precompiled Headers, and set it to Not Using Precompiled Headers there. - -NOTE: Modern versions of VS should be fully supported, but old versions, e.g. -VS6, are not guaranteed to work. - -*) Compilers on Macintosh - -LodePNG has been reported to work both with gcc and LLVM for Macintosh, both for -C and C++. - -*) Other Compilers - -If you encounter problems on any compilers, feel free to let me know and I may -try to fix it if the compiler is modern and standards compliant. - - -10. examples ------------- - -This decoder example shows the most basic usage of LodePNG. More complex -examples can be found on the LodePNG website. - -NOTE: these examples do not support wide-character filenames, you can use an -external method to handle such files and encode or decode in-memory - -10.1. decoder C++ example -------------------------- - -#include "lodepng.h" -#include - -int main(int argc, char *argv[]) { - const char* filename = argc > 1 ? argv[1] : "test.png"; - - //load and decode - std::vector image; - unsigned width, height; - unsigned error = lodepng::decode(image, width, height, filename); - - //if there's an error, display it - if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl; - - //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ... -} - -10.2. decoder C example ------------------------ - -#include "lodepng.h" - -int main(int argc, char *argv[]) { - unsigned error; - unsigned char* image; - size_t width, height; - const char* filename = argc > 1 ? argv[1] : "test.png"; - - error = lodepng_decode32_file(&image, &width, &height, filename); - - if(error) printf("decoder error %u: %s\n", error, lodepng_error_text(error)); - - / * use image here * / - - free(image); - return 0; -} - -11. state settings reference ----------------------------- - -A quick reference of some settings to set on the LodePNGState - -For decoding: - -state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums -state.decoder.zlibsettings.custom_...: use custom inflate function -state.decoder.ignore_crc: ignore CRC checksums -state.decoder.ignore_critical: ignore unknown critical chunks -state.decoder.ignore_end: ignore missing IEND chunk. May fail if this corruption causes other errors -state.decoder.color_convert: convert internal PNG color to chosen one -state.decoder.read_text_chunks: whether to read in text metadata chunks -state.decoder.remember_unknown_chunks: whether to read in unknown chunks -state.info_raw.colortype: desired color type for decoded image -state.info_raw.bitdepth: desired bit depth for decoded image -state.info_raw....: more color settings, see struct LodePNGColorMode -state.info_png....: no settings for decoder but ouput, see struct LodePNGInfo - -For encoding: - -state.encoder.zlibsettings.btype: disable compression by setting it to 0 -state.encoder.zlibsettings.use_lz77: use LZ77 in compression -state.encoder.zlibsettings.windowsize: tweak LZ77 windowsize -state.encoder.zlibsettings.minmatch: tweak min LZ77 length to match -state.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching -state.encoder.zlibsettings.lazymatching: try one more LZ77 matching -state.encoder.zlibsettings.custom_...: use custom deflate function -state.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png -state.encoder.filter_palette_zero: PNG filter strategy for palette -state.encoder.filter_strategy: PNG filter strategy to encode with -state.encoder.force_palette: add palette even if not encoding to one -state.encoder.add_id: add LodePNG identifier and version as a text chunk -state.encoder.text_compression: use compressed text chunks for metadata -state.info_raw.colortype: color type of raw input image you provide -state.info_raw.bitdepth: bit depth of raw input image you provide -state.info_raw: more color settings, see struct LodePNGColorMode -state.info_png.color.colortype: desired color type if auto_convert is false -state.info_png.color.bitdepth: desired bit depth if auto_convert is false -state.info_png.color....: more color settings, see struct LodePNGColorMode -state.info_png....: more PNG related settings, see struct LodePNGInfo - - -12. changes ------------ - -The version number of LodePNG is the date of the change given in the format -yyyymmdd. - -Some changes aren't backwards compatible. Those are indicated with a (!) -symbol. - -Not all changes are listed here, the commit history in github lists more: -https://github.com/lvandeve/lodepng - -*) 10 apr 2023: faster CRC32 implementation, but with larger lookup table. -*) 13 jun 2022: added support for the sBIT chunk. -*) 09 jan 2022: minor decoder speed improvements. -*) 27 jun 2021: added warnings that file reading/writing functions don't support - wide-character filenames (support for this is not planned, opening files is - not the core part of PNG decoding/decoding and is platform dependent). -*) 17 okt 2020: prevent decoding too large text/icc chunks by default. -*) 06 mar 2020: simplified some of the dynamic memory allocations. -*) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct - overflow checks. -*) 14 aug 2019: around 25% faster decoding thanks to huffman lookup tables. -*) 15 jun 2019: (!) auto_choose_color API changed (for bugfix: don't use palette - if gray ICC profile) and non-ICC LodePNGColorProfile renamed to - LodePNGColorStats. -*) 30 dec 2018: code style changes only: removed newlines before opening braces. -*) 10 sep 2018: added way to inspect metadata chunks without full decoding. -*) 19 aug 2018: (!) fixed color mode bKGD is encoded with and made it use - palette index in case of palette. -*) 10 aug 2018: (!) added support for gAMA, cHRM, sRGB and iCCP chunks. This - change is backwards compatible unless you relied on unknown_chunks for those. -*) 11 jun 2018: less restrictive check for pixel size integer overflow -*) 14 jan 2018: allow optionally ignoring a few more recoverable errors -*) 17 sep 2017: fix memory leak for some encoder input error cases -*) 27 nov 2016: grey+alpha auto color model detection bugfix -*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort). -*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within - the limits of pure C90). -*) 08 dec 2015: Made load_file function return error if file can't be opened. -*) 24 okt 2015: Bugfix with decoding to palette output. -*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding. -*) 24 aug 2014: Moved to github -*) 23 aug 2014: Reduced needless memory usage of decoder. -*) 28 jun 2014: Removed fix_png setting, always support palette OOB for - simplicity. Made ColorProfile public. -*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization. -*) 22 dec 2013: Power of two windowsize required for optimization. -*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key. -*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png). -*) 11 mar 2013: (!) Bugfix with custom free. Changed from "my" to "lodepng_" - prefix for the custom allocators and made it possible with a new #define to - use custom ones in your project without needing to change lodepng's code. -*) 28 jan 2013: Bugfix with color key. -*) 27 okt 2012: Tweaks in text chunk keyword length error handling. -*) 8 okt 2012: (!) Added new filter strategy (entropy) and new auto color mode. - (no palette). Better deflate tree encoding. New compression tweak settings. - Faster color conversions while decoding. Some internal cleanups. -*) 23 sep 2012: Reduced warnings in Visual Studio a little bit. -*) 1 sep 2012: (!) Removed #define's for giving custom (de)compression functions - and made it work with function pointers instead. -*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc - and free functions and toggle #defines from compiler flags. Small fixes. -*) 6 may 2012: (!) Made plugging in custom zlib/deflate functions more flexible. -*) 22 apr 2012: (!) Made interface more consistent, renaming a lot. Removed - redundant C++ codec classes. Reduced amount of structs. Everything changed, - but it is cleaner now imho and functionality remains the same. Also fixed - several bugs and shrunk the implementation code. Made new samples. -*) 6 nov 2011: (!) By default, the encoder now automatically chooses the best - PNG color model and bit depth, based on the amount and type of colors of the - raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color. -*) 9 okt 2011: simpler hash chain implementation for the encoder. -*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching. -*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking. - A bug with the PNG filtertype heuristic was fixed, so that it chooses much - better ones (it's quite significant). A setting to do an experimental, slow, - brute force search for PNG filter types is added. -*) 17 aug 2011: (!) changed some C zlib related function names. -*) 16 aug 2011: made the code less wide (max 120 characters per line). -*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors. -*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled. -*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman - to optimize long sequences of zeros. -*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and - LodePNG_InfoColor_canHaveAlpha functions for convenience. -*) 7 nov 2010: added LodePNG_error_text function to get error code description. -*) 30 okt 2010: made decoding slightly faster -*) 26 okt 2010: (!) changed some C function and struct names (more consistent). - Reorganized the documentation and the declaration order in the header. -*) 08 aug 2010: only changed some comments and external samples. -*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version. -*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers. -*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could - read by ignoring the problem but windows apps couldn't. -*) 06 jun 2008: added more error checks for out of memory cases. -*) 26 apr 2008: added a few more checks here and there to ensure more safety. -*) 06 mar 2008: crash with encoding of strings fixed -*) 02 feb 2008: support for international text chunks added (iTXt) -*) 23 jan 2008: small cleanups, and #defines to divide code in sections -*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor. -*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder. -*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added - Also various fixes, such as in the deflate and the padding bits code. -*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved - filtering code of encoder. -*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A - C++ wrapper around this provides an interface almost identical to before. - Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code - are together in these files but it works both for C and C++ compilers. -*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks -*) 30 aug 2007: bug fixed which makes this Borland C++ compatible -*) 09 aug 2007: some VS2005 warnings removed again -*) 21 jul 2007: deflate code placed in new namespace separate from zlib code -*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images -*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing - invalid std::vector element [0] fixed, and level 3 and 4 warnings removed -*) 02 jun 2007: made the encoder add a tag with version by default -*) 27 may 2007: zlib and png code separated (but still in the same file), - simple encoder/decoder functions added for more simple usage cases -*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69), - moved some examples from here to lodepng_examples.cpp -*) 12 may 2007: palette decoding bug fixed -*) 24 apr 2007: changed the license from BSD to the zlib license -*) 11 mar 2007: very simple addition: ability to encode bKGD chunks. -*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding - palettized PNG images. Plus little interface change with palette and texts. -*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes. - Fixed a bug where the end code of a block had length 0 in the Huffman tree. -*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented - and supported by the encoder, resulting in smaller PNGs at the output. -*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone. -*) 24 jan 2007: gave encoder an error interface. Added color conversion from any - greyscale type to 8-bit greyscale with or without alpha. -*) 21 jan 2007: (!) Totally changed the interface. It allows more color types - to convert to and is more uniform. See the manual for how it works now. -*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days: - encode/decode custom tEXt chunks, separate classes for zlib & deflate, and - at last made the decoder give errors for incorrect Adler32 or Crc. -*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel. -*) 29 dec 2006: Added support for encoding images without alpha channel, and - cleaned out code as well as making certain parts faster. -*) 28 dec 2006: Added "Settings" to the encoder. -*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now. - Removed some code duplication in the decoder. Fixed little bug in an example. -*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter. - Fixed a bug of the decoder with 16-bit per color. -*) 15 okt 2006: Changed documentation structure -*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the - given image buffer, however for now it's not compressed. -*) 08 sep 2006: (!) Changed to interface with a Decoder class -*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different - way. Renamed decodePNG to decodePNGGeneric. -*) 29 jul 2006: (!) Changed the interface: image info is now returned as a - struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy. -*) 28 jul 2006: Cleaned the code and added new error checks. - Corrected terminology "deflate" into "inflate". -*) 23 jun 2006: Added SDL example in the documentation in the header, this - example allows easy debugging by displaying the PNG and its transparency. -*) 22 jun 2006: (!) Changed way to obtain error value. Added - loadFile function for convenience. Made decodePNG32 faster. -*) 21 jun 2006: (!) Changed type of info vector to unsigned. - Changed position of palette in info vector. Fixed an important bug that - happened on PNGs with an uncompressed block. -*) 16 jun 2006: Internally changed unsigned into unsigned where - needed, and performed some optimizations. -*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them - in LodePNG namespace. Changed the order of the parameters. Rewrote the - documentation in the header. Renamed files to lodepng.cpp and lodepng.h -*) 22 apr 2006: Optimized and improved some code -*) 07 sep 2005: (!) Changed to std::vector interface -*) 12 aug 2005: Initial release (C++, decoder only) - - -13. contact information ------------------------ - -Feel free to contact me with suggestions, problems, comments, ... concerning -LodePNG. If you encounter a PNG image that doesn't work properly with this -decoder, feel free to send it and I'll use it to find and fix the problem. - -My email address is (puzzle the account and domain together with an @ symbol): -Domain: gmail dot com. -Account: lode dot vandevenne. - - -Copyright (c) 2005-2022 Lode Vandevenne -*/ diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/resources/mesh.nim --- a/src/semicongine/resources/mesh.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,371 +0,0 @@ -import std/strutils -import std/json -import std/logging -import std/tables -import std/strformat -import std/streams - -import ../mesh -import ../material -import ../core - -import ./image - -type - glTFHeader = object - magic: uint32 - version: uint32 - length: uint32 - glTFData = object - structuredContent: JsonNode - binaryBufferData: seq[uint8] - -const - JSON_CHUNK = 0x4E4F534A - BINARY_CHUNK = 0x004E4942 - ACCESSOR_TYPE_MAP = { - 5120: Int8, - 5121: UInt8, - 5122: Int16, - 5123: UInt16, - 5125: UInt32, - 5126: Float32, - }.toTable - SAMPLER_FILTER_MODE_MAP = { - 9728: VK_FILTER_NEAREST, - 9729: VK_FILTER_LINEAR, - 9984: VK_FILTER_NEAREST, - 9985: VK_FILTER_LINEAR, - 9986: VK_FILTER_NEAREST, - 9987: VK_FILTER_LINEAR, - }.toTable - SAMPLER_WRAP_MODE_MAP = { - 33071: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - 33648: VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, - 10497: VK_SAMPLER_ADDRESS_MODE_REPEAT - }.toTable - GLTF_MATERIAL_MAPPING = { - "color": "baseColorFactor", - "emissiveColor": "emissiveFactor", - "metallic": "metallicFactor", - "roughness", "roughnessFactor", - "baseTexture": "baseColorTexture", - "metallicRoughnessTexture": "metallicRoughnessTexture", - "normalTexture": "normalTexture", - "occlusionTexture": "occlusionTexture", - "emissiveTexture": "emissiveTexture", - }.toTable - -proc getGPUType(accessor: JsonNode, attribute: string): DataType = - # TODO: no full support for all datatypes that glTF may provide - # semicongine/core/gpu_data should maybe generated with macros to allow for all combinations - let componentType = ACCESSOR_TYPE_MAP[accessor["componentType"].getInt()] - let theType = accessor["type"].getStr() - case theType - of "SCALAR": - return componentType - of "VEC2": - case componentType - of UInt32: return Vec2U32 - of Float32: return Vec2F32 - else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") - of "VEC3": - case componentType - of UInt32: return Vec3U32 - of Float32: return Vec3F32 - else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") - of "VEC4": - case componentType - of UInt32: return Vec4U32 - of Float32: return Vec4F32 - else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") - of "MAT2": - case componentType - of Float32: return Vec4F32 - else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") - of "MAT3": - case componentType - of Float32: return Vec4F32 - else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") - of "MAT4": - case componentType - of Float32: return Vec4F32 - else: raise newException(Exception, &"Unsupported data type for attribute '{attribute}': {componentType} {theType}") - -proc getBufferViewData(bufferView: JsonNode, mainBuffer: seq[uint8], baseBufferOffset=0): seq[uint8] = - assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported" - - result = newSeq[uint8](bufferView["byteLength"].getInt()) - let bufferOffset = bufferView["byteOffset"].getInt() + baseBufferOffset - var dstPointer = addr result[0] - - if bufferView.hasKey("byteStride"): - raise newException(Exception, "Unsupported feature: byteStride in buffer view") - copyMem(dstPointer, addr mainBuffer[bufferOffset], result.len) - -proc getAccessorData(root: JsonNode, accessor: JsonNode, mainBuffer: seq[uint8]): DataList = - result = initDataList(thetype=accessor.getGPUType("??")) - result.setLen(accessor["count"].getInt()) - - let bufferView = root["bufferViews"][accessor["bufferView"].getInt()] - assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported" - - if accessor.hasKey("sparse"): - raise newException(Exception, "Sparce accessors are currently not implemented") - - let accessorOffset = if accessor.hasKey("byteOffset"): accessor["byteOffset"].getInt() else: 0 - let length = bufferView["byteLength"].getInt() - let bufferOffset = bufferView["byteOffset"].getInt() + accessorOffset - var dstPointer = result.getRawData()[0] - - if bufferView.hasKey("byteStride"): - warn "Congratulations, you try to test a feature (loading buffer data with stride attributes) that we have no idea where it is used and how it can be tested (need a coresponding *.glb file)." - # we don't support stride, have to convert stuff here... does this even work? - for i in 0 ..< int(result.len): - copyMem(dstPointer, addr mainBuffer[bufferOffset + i * bufferView["byteStride"].getInt()], int(result.thetype.size)) - dstPointer = cast[pointer](cast[int](dstPointer) + result.thetype.size) - else: - copyMem(dstPointer, addr mainBuffer[bufferOffset], length) - -proc loadImage(root: JsonNode, imageIndex: int, mainBuffer: seq[uint8]): Image = - if root["images"][imageIndex].hasKey("uri"): - raise newException(Exception, "Unsupported feature: Load images from external files") - - let bufferView = root["bufferViews"][root["images"][imageIndex]["bufferView"].getInt()] - let imgData = newStringStream(cast[string](getBufferViewData(bufferView, mainBuffer))) - - let imageType = root["images"][imageIndex]["mimeType"].getStr() - case imageType - of "image/bmp": - result = readBMP(imgData) - of "image/png": - result = readPNG(imgData) - else: - raise newException(Exception, "Unsupported feature: Load image of type " & imageType) - -proc loadTexture(root: JsonNode, textureIndex: int, mainBuffer: seq[uint8]): Texture = - let textureNode = root["textures"][textureIndex] - result.image = loadImage(root, textureNode["source"].getInt(), mainBuffer) - result.name = root["images"][textureNode["source"].getInt()]["name"].getStr() - if result.name == "": - result.name = &"Texture{textureIndex}" - - if textureNode.hasKey("sampler"): - let sampler = root["samplers"][textureNode["sampler"].getInt()] - if sampler.hasKey("magFilter"): - result.sampler.magnification = SAMPLER_FILTER_MODE_MAP[sampler["magFilter"].getInt()] - if sampler.hasKey("minFilter"): - result.sampler.minification = SAMPLER_FILTER_MODE_MAP[sampler["minFilter"].getInt()] - if sampler.hasKey("wrapS"): - result.sampler.wrapModeS = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()] - if sampler.hasKey("wrapT"): - result.sampler.wrapModeT = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()] - - -proc loadMaterial(root: JsonNode, materialNode: JsonNode, defaultMaterial: MaterialType, mainBuffer: seq[uint8]): MaterialData = - let pbr = materialNode["pbrMetallicRoughness"] - var attributes: Table[string, DataList] - - # color - if defaultMaterial.attributes.contains("color"): - attributes["color"] = initDataList(thetype=Vec4F32) - if pbr.hasKey(GLTF_MATERIAL_MAPPING["color"]): - setValue(attributes["color"], @[newVec4f( - pbr[GLTF_MATERIAL_MAPPING["color"]][0].getFloat(), - pbr[GLTF_MATERIAL_MAPPING["color"]][1].getFloat(), - pbr[GLTF_MATERIAL_MAPPING["color"]][2].getFloat(), - pbr[GLTF_MATERIAL_MAPPING["color"]][3].getFloat(), - )]) - else: - setValue(attributes["color"], @[newVec4f(1, 1, 1, 1)]) - - # pbr material values - for factor in ["metallic", "roughness"]: - if defaultMaterial.attributes.contains(factor): - attributes[factor] = initDataList(thetype=Float32) - if pbr.hasKey(GLTF_MATERIAL_MAPPING[factor]): - setValue(attributes[factor], @[float32(pbr[GLTF_MATERIAL_MAPPING[factor]].getFloat())]) - else: - setValue(attributes[factor], @[0.5'f32]) - - # pbr material textures - for texture in ["baseTexture", "metallicRoughnessTexture"]: - if defaultMaterial.attributes.contains(texture): - attributes[texture] = initDataList(thetype=TextureType) - # attributes[texture & "Index"] = initDataList(thetype=UInt8) - if pbr.hasKey(GLTF_MATERIAL_MAPPING[texture]): - setValue(attributes[texture], @[loadTexture(root, pbr[GLTF_MATERIAL_MAPPING[texture]]["index"].getInt(), mainBuffer)]) - # setValue(attributes[texture & "Index"], @[pbr[GLTF_MATERIAL_MAPPING[texture]].getOrDefault("texCoord").getInt(0).uint8]) - else: - setValue(attributes[texture], @[EMPTY_TEXTURE]) - # setValue(attributes[texture & "Index"], @[0'u8]) - - # generic material textures - for texture in ["normalTexture", "occlusionTexture", "emissiveTexture"]: - if defaultMaterial.attributes.contains(texture): - attributes[texture] = initDataList(thetype=TextureType) - # attributes[texture & "Index"] = initDataList(thetype=UInt8) - if materialNode.hasKey(GLTF_MATERIAL_MAPPING[texture]): - setValue(attributes[texture], @[loadTexture(root, materialNode[texture]["index"].getInt(), mainBuffer)]) - # setValue(attributes[texture & "Index"], @[materialNode[texture].getOrDefault("texCoord").getInt(0).uint8]) - else: - setValue(attributes[texture], @[EMPTY_TEXTURE]) - # setValue(attributes[texture & "Index"], @[0'u8]) - - # emissiv color - if defaultMaterial.attributes.contains("emissiveColor"): - attributes["emissiveColor"] = initDataList(thetype=Vec3F32) - if materialNode.hasKey(GLTF_MATERIAL_MAPPING["emissiveColor"]): - setValue(attributes["emissiveColor"], @[newVec3f( - materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][0].getFloat(), - materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][1].getFloat(), - materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][2].getFloat(), - )]) - else: - setValue(attributes["emissiveColor"], @[newVec3f(1'f32, 1'f32, 1'f32)]) - - result = initMaterialData(materialType=defaultMaterial, name=materialNode["name"].getStr(), attributes=attributes) - -proc loadMesh(meshname: string, root: JsonNode, primitiveNode: JsonNode, defaultMaterial: MaterialType, mainBuffer: seq[uint8]): Mesh = - if primitiveNode.hasKey("mode") and primitiveNode["mode"].getInt() != 4: - raise newException(Exception, "Currently only TRIANGLE mode is supported for geometry mode") - - var indexType = None - let indexed = primitiveNode.hasKey("indices") - if indexed: - # TODO: Tiny indices - var indexCount = root["accessors"][primitiveNode["indices"].getInt()]["count"].getInt() - if indexCount < int(high(uint16)): - indexType = Small - else: - indexType = Big - - result = Mesh( - instanceTransforms: @[Unit4F32], - indexType: indexType, - name: meshname, - vertexCount: 0, - ) - - for attribute, accessor in primitiveNode["attributes"].pairs: - let data = root.getAccessorData(root["accessors"][accessor.getInt()], mainBuffer) - if result.vertexCount == 0: - result.vertexCount = data.len - assert data.len == result.vertexCount - result[].initVertexAttribute(attribute.toLowerAscii, data) - - if primitiveNode.hasKey("material"): - let materialId = primitiveNode["material"].getInt() - result[].material = loadMaterial(root, root["materials"][materialId], defaultMaterial, mainBuffer) - else: - result[].material = EMPTY_MATERIAL.initMaterialData() - - if primitiveNode.hasKey("indices"): - assert result[].indexType != None - let data = root.getAccessorData(root["accessors"][primitiveNode["indices"].getInt()], mainBuffer) - var tri: seq[int] - case data.thetype - of UInt16: - for entry in getValues[uint16](data)[]: - tri.add int(entry) - if tri.len == 3: - # FYI gltf uses counter-clockwise indexing - result[].appendIndicesData(tri[0], tri[1], tri[2]) - tri.setLen(0) - of UInt32: - for entry in getValues[uint32](data)[]: - tri.add int(entry) - if tri.len == 3: - # FYI gltf uses counter-clockwise indexing - result[].appendIndicesData(tri[0], tri[1], tri[2]) - tri.setLen(0) - else: - raise newException(Exception, &"Unsupported index data type: {data.thetype}") - # TODO: getting from gltf to vulkan system is still messed up somehow, see other TODO - transform[Vec3f](result[], "position", scale(1, -1, 1)) - -proc loadNode(root: JsonNode, node: JsonNode, defaultMaterial: MaterialType, mainBuffer: var seq[uint8]): MeshTree = - result = MeshTree() - # mesh - if node.hasKey("mesh"): - let mesh = root["meshes"][node["mesh"].getInt()] - for primitive in mesh["primitives"]: - result.children.add MeshTree(mesh: loadMesh(mesh["name"].getStr(), root, primitive, defaultMaterial, mainBuffer)) - - # transformation - if node.hasKey("matrix"): - var mat: Mat4 - for i in 0 ..< node["matrix"].len: - mat[i] = node["matrix"][i].getFloat() - result.transform = mat - else: - var (t, r, s) = (Unit4F32, Unit4F32, Unit4F32) - if node.hasKey("translation"): - t = translate( - float32(node["translation"][0].getFloat()), - float32(node["translation"][1].getFloat()), - float32(node["translation"][2].getFloat()) - ) - if node.hasKey("rotation"): - t = rotate( - float32(node["rotation"][3].getFloat()), - newVec3f( - float32(node["rotation"][0].getFloat()), - float32(node["rotation"][1].getFloat()), - float32(node["rotation"][2].getFloat()) - ) - ) - if node.hasKey("scale"): - t = scale( - float32(node["scale"][0].getFloat()), - float32(node["scale"][1].getFloat()), - float32(node["scale"][2].getFloat()) - ) - result.transform = t * r * s - result.transform = scale(1, -1, 1) * result.transform - - # children - if node.hasKey("children"): - for childNode in node["children"]: - result.children.add loadNode(root, root["nodes"][childNode.getInt()], defaultMaterial, mainBuffer) - -proc loadMeshTree(root: JsonNode, scenenode: JsonNode, defaultMaterial: MaterialType, mainBuffer: var seq[uint8]): MeshTree = - result = MeshTree() - for nodeId in scenenode["nodes"]: - result.children.add loadNode(root, root["nodes"][nodeId.getInt()], defaultMaterial, mainBuffer) - # TODO: getting from gltf to vulkan system is still messed up somehow (i.e. not consistent for different files), see other TODO - # result.transform = scale(1, -1, 1) - result.updateTransforms() - - -proc readglTF*(stream: Stream, defaultMaterial: MaterialType): seq[MeshTree] = - var - header: glTFHeader - data: glTFData - - for name, value in fieldPairs(header): - stream.read(value) - - assert header.magic == 0x46546C67 - assert header.version == 2 - - var chunkLength = stream.readUint32() - assert stream.readUint32() == JSON_CHUNK - data.structuredContent = parseJson(stream.readStr(int(chunkLength))) - - chunkLength = stream.readUint32() - assert stream.readUint32() == BINARY_CHUNK - data.binaryBufferData.setLen(chunkLength) - assert stream.readData(addr data.binaryBufferData[0], int(chunkLength)) == int(chunkLength) - - # check that the refered buffer is the same as the binary chunk - # external binary buffers are not supported - assert data.structuredContent["buffers"].len == 1 - assert not data.structuredContent["buffers"][0].hasKey("uri") - let bufferLenDiff = int(chunkLength) - data.structuredContent["buffers"][0]["byteLength"].getInt() - assert 0 <= bufferLenDiff <= 3 # binary buffer may be aligned to 4 bytes - - debug "Loading mesh: ", data.structuredContent.pretty - - for scenedata in data.structuredContent["scenes"]: - result.add data.structuredContent.loadMeshTree(scenedata, defaultMaterial, data.binaryBufferData) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/resources/stb_truetype.h --- a/src/semicongine/resources/stb_truetype.h Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5077 +0,0 @@ -// stb_truetype.h - v1.26 - public domain -// authored from 2009-2021 by Sean Barrett / RAD Game Tools -// -// ======================================================================= -// -// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES -// -// This library does no range checking of the offsets found in the file, -// meaning an attacker can use it to read arbitrary memory. -// -// ======================================================================= -// -// This library processes TrueType files: -// parse files -// extract glyph metrics -// extract glyph shapes -// render glyphs to one-channel bitmaps with antialiasing (box filter) -// render glyphs to one-channel SDF bitmaps (signed-distance field/function) -// -// Todo: -// non-MS cmaps -// crashproof on bad data -// hinting? (no longer patented) -// cleartype-style AA? -// optimize: use simple memory allocator for intermediates -// optimize: build edge-list directly from curves -// optimize: rasterize directly from curves? -// -// ADDITIONAL CONTRIBUTORS -// -// Mikko Mononen: compound shape support, more cmap formats -// Tor Andersson: kerning, subpixel rendering -// Dougall Johnson: OpenType / Type 2 font handling -// Daniel Ribeiro Maciel: basic GPOS-based kerning -// -// Misc other: -// Ryan Gordon -// Simon Glass -// github:IntellectualKitty -// Imanol Celaya -// Daniel Ribeiro Maciel -// -// Bug/warning reports/fixes: -// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe -// Cass Everitt Martins Mozeiko github:aloucks -// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam -// Brian Hook Omar Cornut github:vassvik -// Walter van Niftrik Ryan Griege -// David Gow Peter LaValle -// David Given Sergey Popov -// Ivan-Assen Ivanov Giumo X. Clanjor -// Anthony Pesch Higor Euripedes -// Johan Duparc Thomas Fields -// Hou Qiming Derek Vinyard -// Rob Loach Cort Stratton -// Kenney Phillis Jr. Brian Costabile -// Ken Voskuil (kaesve) -// -// VERSION HISTORY -// -// 1.26 (2021-08-28) fix broken rasterizer -// 1.25 (2021-07-11) many fixes -// 1.24 (2020-02-05) fix warning -// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) -// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined -// 1.21 (2019-02-25) fix warning -// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() -// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod -// 1.18 (2018-01-29) add missing function -// 1.17 (2017-07-23) make more arguments const; doc fix -// 1.16 (2017-07-12) SDF support -// 1.15 (2017-03-03) make more arguments const -// 1.14 (2017-01-16) num-fonts-in-TTC function -// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts -// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual -// 1.11 (2016-04-02) fix unused-variable warning -// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef -// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly -// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges -// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; -// variant PackFontRanges to pack and render in separate phases; -// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); -// fixed an assert() bug in the new rasterizer -// replace assert() with STBTT_assert() in new rasterizer -// -// Full history can be found at the end of this file. -// -// LICENSE -// -// See end of file for license information. -// -// USAGE -// -// Include this file in whatever places need to refer to it. In ONE C/C++ -// file, write: -// #define STB_TRUETYPE_IMPLEMENTATION -// before the #include of this file. This expands out the actual -// implementation into that C/C++ file. -// -// To make the implementation private to the file that generates the implementation, -// #define STBTT_STATIC -// -// Simple 3D API (don't ship this, but it's fine for tools and quick start) -// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture -// stbtt_GetBakedQuad() -- compute quad to draw for a given char -// -// Improved 3D API (more shippable): -// #include "stb_rect_pack.h" -- optional, but you really want it -// stbtt_PackBegin() -// stbtt_PackSetOversampling() -- for improved quality on small fonts -// stbtt_PackFontRanges() -- pack and renders -// stbtt_PackEnd() -// stbtt_GetPackedQuad() -// -// "Load" a font file from a memory buffer (you have to keep the buffer loaded) -// stbtt_InitFont() -// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections -// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections -// -// Render a unicode codepoint to a bitmap -// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap -// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide -// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be -// -// Character advance/positioning -// stbtt_GetCodepointHMetrics() -// stbtt_GetFontVMetrics() -// stbtt_GetFontVMetricsOS2() -// stbtt_GetCodepointKernAdvance() -// -// Starting with version 1.06, the rasterizer was replaced with a new, -// faster and generally-more-precise rasterizer. The new rasterizer more -// accurately measures pixel coverage for anti-aliasing, except in the case -// where multiple shapes overlap, in which case it overestimates the AA pixel -// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If -// this turns out to be a problem, you can re-enable the old rasterizer with -// #define STBTT_RASTERIZER_VERSION 1 -// which will incur about a 15% speed hit. -// -// ADDITIONAL DOCUMENTATION -// -// Immediately after this block comment are a series of sample programs. -// -// After the sample programs is the "header file" section. This section -// includes documentation for each API function. -// -// Some important concepts to understand to use this library: -// -// Codepoint -// Characters are defined by unicode codepoints, e.g. 65 is -// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is -// the hiragana for "ma". -// -// Glyph -// A visual character shape (every codepoint is rendered as -// some glyph) -// -// Glyph index -// A font-specific integer ID representing a glyph -// -// Baseline -// Glyph shapes are defined relative to a baseline, which is the -// bottom of uppercase characters. Characters extend both above -// and below the baseline. -// -// Current Point -// As you draw text to the screen, you keep track of a "current point" -// which is the origin of each character. The current point's vertical -// position is the baseline. Even "baked fonts" use this model. -// -// Vertical Font Metrics -// The vertical qualities of the font, used to vertically position -// and space the characters. See docs for stbtt_GetFontVMetrics. -// -// Font Size in Pixels or Points -// The preferred interface for specifying font sizes in stb_truetype -// is to specify how tall the font's vertical extent should be in pixels. -// If that sounds good enough, skip the next paragraph. -// -// Most font APIs instead use "points", which are a common typographic -// measurement for describing font size, defined as 72 points per inch. -// stb_truetype provides a point API for compatibility. However, true -// "per inch" conventions don't make much sense on computer displays -// since different monitors have different number of pixels per -// inch. For example, Windows traditionally uses a convention that -// there are 96 pixels per inch, thus making 'inch' measurements have -// nothing to do with inches, and thus effectively defining a point to -// be 1.333 pixels. Additionally, the TrueType font data provides -// an explicit scale factor to scale a given font's glyphs to points, -// but the author has observed that this scale factor is often wrong -// for non-commercial fonts, thus making fonts scaled in points -// according to the TrueType spec incoherently sized in practice. -// -// DETAILED USAGE: -// -// Scale: -// Select how high you want the font to be, in points or pixels. -// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute -// a scale factor SF that will be used by all other functions. -// -// Baseline: -// You need to select a y-coordinate that is the baseline of where -// your text will appear. Call GetFontBoundingBox to get the baseline-relative -// bounding box for all characters. SF*-y0 will be the distance in pixels -// that the worst-case character could extend above the baseline, so if -// you want the top edge of characters to appear at the top of the -// screen where y=0, then you would set the baseline to SF*-y0. -// -// Current point: -// Set the current point where the first character will appear. The -// first character could extend left of the current point; this is font -// dependent. You can either choose a current point that is the leftmost -// point and hope, or add some padding, or check the bounding box or -// left-side-bearing of the first character to be displayed and set -// the current point based on that. -// -// Displaying a character: -// Compute the bounding box of the character. It will contain signed values -// relative to . I.e. if it returns x0,y0,x1,y1, -// then the character should be displayed in the rectangle from -// to = 32 && *text < 128) { - stbtt_aligned_quad q; - stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 - glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); - glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); - glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); - glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); - } - ++text; - } - glEnd(); -} -#endif -// -// -////////////////////////////////////////////////////////////////////////////// -// -// Complete program (this compiles): get a single bitmap, print as ASCII art -// -#if 0 -#include -#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation -#include "stb_truetype.h" - -char ttf_buffer[1<<25]; - -int main(int argc, char **argv) -{ - stbtt_fontinfo font; - unsigned char *bitmap; - int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); - - fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); - - stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); - bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); - - for (j=0; j < h; ++j) { - for (i=0; i < w; ++i) - putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); - putchar('\n'); - } - return 0; -} -#endif -// -// Output: -// -// .ii. -// @@@@@@. -// V@Mio@@o -// :i. V@V -// :oM@@M -// :@@@MM@M -// @@o o@M -// :@@. M@M -// @@@o@@@@ -// :M@@V:@@. -// -////////////////////////////////////////////////////////////////////////////// -// -// Complete program: print "Hello World!" banner, with bugs -// -#if 0 -char buffer[24<<20]; -unsigned char screen[20][79]; - -int main(int arg, char **argv) -{ - stbtt_fontinfo font; - int i,j,ascent,baseline,ch=0; - float scale, xpos=2; // leave a little padding in case the character extends left - char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness - - fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); - stbtt_InitFont(&font, buffer, 0); - - scale = stbtt_ScaleForPixelHeight(&font, 15); - stbtt_GetFontVMetrics(&font, &ascent,0,0); - baseline = (int) (ascent*scale); - - while (text[ch]) { - int advance,lsb,x0,y0,x1,y1; - float x_shift = xpos - (float) floor(xpos); - stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); - stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); - stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); - // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong - // because this API is really for baking character bitmaps into textures. if you want to render - // a sequence of characters, you really need to render each bitmap to a temp buffer, then - // "alpha blend" that into the working buffer - xpos += (advance * scale); - if (text[ch+1]) - xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); - ++ch; - } - - for (j=0; j < 20; ++j) { - for (i=0; i < 78; ++i) - putchar(" .:ioVM@"[screen[j][i]>>5]); - putchar('\n'); - } - - return 0; -} -#endif - - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// -//// -//// INTEGRATION WITH YOUR CODEBASE -//// -//// The following sections allow you to supply alternate definitions -//// of C library functions used by stb_truetype, e.g. if you don't -//// link with the C runtime library. - -#ifdef STB_TRUETYPE_IMPLEMENTATION - // #define your own (u)stbtt_int8/16/32 before including to override this - #ifndef stbtt_uint8 - typedef unsigned char stbtt_uint8; - typedef signed char stbtt_int8; - typedef unsigned short stbtt_uint16; - typedef signed short stbtt_int16; - typedef unsigned int stbtt_uint32; - typedef signed int stbtt_int32; - #endif - - typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; - typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; - - // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h - #ifndef STBTT_ifloor - #include - #define STBTT_ifloor(x) ((int) floor(x)) - #define STBTT_iceil(x) ((int) ceil(x)) - #endif - - #ifndef STBTT_sqrt - #include - #define STBTT_sqrt(x) sqrt(x) - #define STBTT_pow(x,y) pow(x,y) - #endif - - #ifndef STBTT_fmod - #include - #define STBTT_fmod(x,y) fmod(x,y) - #endif - - #ifndef STBTT_cos - #include - #define STBTT_cos(x) cos(x) - #define STBTT_acos(x) acos(x) - #endif - - #ifndef STBTT_fabs - #include - #define STBTT_fabs(x) fabs(x) - #endif - - // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h - #ifndef STBTT_malloc - #include - #define STBTT_malloc(x,u) ((void)(u),malloc(x)) - #define STBTT_free(x,u) ((void)(u),free(x)) - #endif - - #ifndef STBTT_assert - #include - #define STBTT_assert(x) assert(x) - #endif - - #ifndef STBTT_strlen - #include - #define STBTT_strlen(x) strlen(x) - #endif - - #ifndef STBTT_memcpy - #include - #define STBTT_memcpy memcpy - #define STBTT_memset memset - #endif -#endif - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -//// -//// INTERFACE -//// -//// - -#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ -#define __STB_INCLUDE_STB_TRUETYPE_H__ - -#ifdef STBTT_STATIC -#define STBTT_DEF static -#else -#define STBTT_DEF extern -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// private structure -typedef struct -{ - unsigned char *data; - int cursor; - int size; -} stbtt__buf; - -////////////////////////////////////////////////////////////////////////////// -// -// TEXTURE BAKING API -// -// If you use this API, you only have to call two functions ever. -// - -typedef struct -{ - unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; -} stbtt_bakedchar; - -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) - float pixel_height, // height of font in pixels - unsigned char *pixels, int pw, int ph, // bitmap to be filled in - int first_char, int num_chars, // characters to bake - stbtt_bakedchar *chardata); // you allocate this, it's num_chars long -// if return is positive, the first unused row of the bitmap -// if return is negative, returns the negative of the number of characters that fit -// if return is 0, no characters fit and no rows were used -// This uses a very crappy packing. - -typedef struct -{ - float x0,y0,s0,t0; // top-left - float x1,y1,s1,t1; // bottom-right -} stbtt_aligned_quad; - -STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above - int char_index, // character to display - float *xpos, float *ypos, // pointers to current position in screen pixel space - stbtt_aligned_quad *q, // output: quad to draw - int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier -// Call GetBakedQuad with char_index = 'character - first_char', and it -// creates the quad you need to draw and advances the current position. -// -// The coordinate system used assumes y increases downwards. -// -// Characters will extend both above and below the current position; -// see discussion of "BASELINE" above. -// -// It's inefficient; you might want to c&p it and optimize it. - -STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); -// Query the font vertical metrics without having to create a font first. - - -////////////////////////////////////////////////////////////////////////////// -// -// NEW TEXTURE BAKING API -// -// This provides options for packing multiple fonts into one atlas, not -// perfectly but better than nothing. - -typedef struct -{ - unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; - float xoff2,yoff2; -} stbtt_packedchar; - -typedef struct stbtt_pack_context stbtt_pack_context; -typedef struct stbtt_fontinfo stbtt_fontinfo; -#ifndef STB_RECT_PACK_VERSION -typedef struct stbrp_rect stbrp_rect; -#endif - -STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); -// Initializes a packing context stored in the passed-in stbtt_pack_context. -// Future calls using this context will pack characters into the bitmap passed -// in here: a 1-channel bitmap that is width * height. stride_in_bytes is -// the distance from one row to the next (or 0 to mean they are packed tightly -// together). "padding" is the amount of padding to leave between each -// character (normally you want '1' for bitmaps you'll use as textures with -// bilinear filtering). -// -// Returns 0 on failure, 1 on success. - -STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); -// Cleans up the packing context and frees all memory. - -#define STBTT_POINT_SIZE(x) (-(x)) - -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, - int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); -// Creates character bitmaps from the font_index'th font found in fontdata (use -// font_index=0 if you don't know what that is). It creates num_chars_in_range -// bitmaps for characters with unicode values starting at first_unicode_char_in_range -// and increasing. Data for how to render them is stored in chardata_for_range; -// pass these to stbtt_GetPackedQuad to get back renderable quads. -// -// font_size is the full height of the character from ascender to descender, -// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed -// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() -// and pass that result as 'font_size': -// ..., 20 , ... // font max minus min y is 20 pixels tall -// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall - -typedef struct -{ - float font_size; - int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint - int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints - int num_chars; - stbtt_packedchar *chardata_for_range; // output - unsigned char h_oversample, v_oversample; // don't set these, they're used internally -} stbtt_pack_range; - -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); -// Creates character bitmaps from multiple ranges of characters stored in -// ranges. This will usually create a better-packed bitmap than multiple -// calls to stbtt_PackFontRange. Note that you can call this multiple -// times within a single PackBegin/PackEnd. - -STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); -// Oversampling a font increases the quality by allowing higher-quality subpixel -// positioning, and is especially valuable at smaller text sizes. -// -// This function sets the amount of oversampling for all following calls to -// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given -// pack context. The default (no oversampling) is achieved by h_oversample=1 -// and v_oversample=1. The total number of pixels required is -// h_oversample*v_oversample larger than the default; for example, 2x2 -// oversampling requires 4x the storage of 1x1. For best results, render -// oversampled textures with bilinear filtering. Look at the readme in -// stb/tests/oversample for information about oversampled fonts -// -// To use with PackFontRangesGather etc., you must set it before calls -// call to PackFontRangesGatherRects. - -STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); -// If skip != 0, this tells stb_truetype to skip any codepoints for which -// there is no corresponding glyph. If skip=0, which is the default, then -// codepoints without a glyph recived the font's "missing character" glyph, -// typically an empty box by convention. - -STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above - int char_index, // character to display - float *xpos, float *ypos, // pointers to current position in screen pixel space - stbtt_aligned_quad *q, // output: quad to draw - int align_to_integer); - -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); -STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); -// Calling these functions in sequence is roughly equivalent to calling -// stbtt_PackFontRanges(). If you more control over the packing of multiple -// fonts, or if you want to pack custom data into a font texture, take a look -// at the source to of stbtt_PackFontRanges() and create a custom version -// using these functions, e.g. call GatherRects multiple times, -// building up a single array of rects, then call PackRects once, -// then call RenderIntoRects repeatedly. This may result in a -// better packing than calling PackFontRanges multiple times -// (or it may not). - -// this is an opaque structure that you shouldn't mess with which holds -// all the context needed from PackBegin to PackEnd. -struct stbtt_pack_context { - void *user_allocator_context; - void *pack_info; - int width; - int height; - int stride_in_bytes; - int padding; - int skip_missing; - unsigned int h_oversample, v_oversample; - unsigned char *pixels; - void *nodes; -}; - -////////////////////////////////////////////////////////////////////////////// -// -// FONT LOADING -// -// - -STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); -// This function will determine the number of fonts in a font file. TrueType -// collection (.ttc) files may contain multiple fonts, while TrueType font -// (.ttf) files only contain one font. The number of fonts can be used for -// indexing with the previous function where the index is between zero and one -// less than the total fonts. If an error occurs, -1 is returned. - -STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); -// Each .ttf/.ttc file may have more than one font. Each font has a sequential -// index number starting from 0. Call this function to get the font offset for -// a given index; it returns -1 if the index is out of range. A regular .ttf -// file will only define one font and it always be at offset 0, so it will -// return '0' for index 0, and -1 for all other indices. - -// The following structure is defined publicly so you can declare one on -// the stack or as a global or etc, but you should treat it as opaque. -struct stbtt_fontinfo -{ - void * userdata; - unsigned char * data; // pointer to .ttf file - int fontstart; // offset of start of font - - int numGlyphs; // number of glyphs, needed for range checking - - int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf - int index_map; // a cmap mapping for our chosen character encoding - int indexToLocFormat; // format needed to map from glyph index to glyph - - stbtt__buf cff; // cff font data - stbtt__buf charstrings; // the charstring index - stbtt__buf gsubrs; // global charstring subroutines index - stbtt__buf subrs; // private charstring subroutines index - stbtt__buf fontdicts; // array of font dicts - stbtt__buf fdselect; // map from glyph to fontdict -}; - -STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); -// Given an offset into the file that defines a font, this function builds -// the necessary cached info for the rest of the system. You must allocate -// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't -// need to do anything special to free it, because the contents are pure -// value data with no additional data structures. Returns 0 on failure. - - -////////////////////////////////////////////////////////////////////////////// -// -// CHARACTER TO GLYPH-INDEX CONVERSIOn - -STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); -// If you're going to perform multiple operations on the same character -// and you want a speed-up, call this function with the character you're -// going to process, then use glyph-based functions instead of the -// codepoint-based functions. -// Returns 0 if the character codepoint is not defined in the font. - - -////////////////////////////////////////////////////////////////////////////// -// -// CHARACTER PROPERTIES -// - -STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); -// computes a scale factor to produce a font whose "height" is 'pixels' tall. -// Height is measured as the distance from the highest ascender to the lowest -// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics -// and computing: -// scale = pixels / (ascent - descent) -// so if you prefer to measure height by the ascent only, use a similar calculation. - -STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); -// computes a scale factor to produce a font whose EM size is mapped to -// 'pixels' tall. This is probably what traditional APIs compute, but -// I'm not positive. - -STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); -// ascent is the coordinate above the baseline the font extends; descent -// is the coordinate below the baseline the font extends (i.e. it is typically negative) -// lineGap is the spacing between one row's descent and the next row's ascent... -// so you should advance the vertical position by "*ascent - *descent + *lineGap" -// these are expressed in unscaled coordinates, so you must multiply by -// the scale factor for a given size - -STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); -// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 -// table (specific to MS/Windows TTF files). -// -// Returns 1 on success (table present), 0 on failure. - -STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); -// the bounding box around all possible characters - -STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); -// leftSideBearing is the offset from the current horizontal position to the left edge of the character -// advanceWidth is the offset from the current horizontal position to the next horizontal position -// these are expressed in unscaled coordinates - -STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); -// an additional amount to add to the 'advance' value between ch1 and ch2 - -STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); -// Gets the bounding box of the visible part of the glyph, in unscaled coordinates - -STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); -STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); -// as above, but takes one or more glyph indices for greater efficiency - -typedef struct stbtt_kerningentry -{ - int glyph1; // use stbtt_FindGlyphIndex - int glyph2; - int advance; -} stbtt_kerningentry; - -STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); -STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); -// Retrieves a complete list of all of the kerning pairs provided by the font -// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. -// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) - -////////////////////////////////////////////////////////////////////////////// -// -// GLYPH SHAPES (you probably don't need these, but they have to go before -// the bitmaps for C declaration-order reasons) -// - -#ifndef STBTT_vmove // you can predefine these to use different values (but why?) - enum { - STBTT_vmove=1, - STBTT_vline, - STBTT_vcurve, - STBTT_vcubic - }; -#endif - -#ifndef stbtt_vertex // you can predefine this to use different values - // (we share this with other code at RAD) - #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file - typedef struct - { - stbtt_vertex_type x,y,cx,cy,cx1,cy1; - unsigned char type,padding; - } stbtt_vertex; -#endif - -STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); -// returns non-zero if nothing is drawn for this glyph - -STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); -// returns # of vertices and fills *vertices with the pointer to them -// these are expressed in "unscaled" coordinates -// -// The shape is a series of contours. Each one starts with -// a STBTT_moveto, then consists of a series of mixed -// STBTT_lineto and STBTT_curveto segments. A lineto -// draws a line from previous endpoint to its x,y; a curveto -// draws a quadratic bezier from previous endpoint to -// its x,y, using cx,cy as the bezier control point. - -STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); -// frees the data allocated above - -STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); -STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); -STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); -// fills svg with the character's SVG data. -// returns data size or 0 if SVG not found. - -////////////////////////////////////////////////////////////////////////////// -// -// BITMAP RENDERING -// - -STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); -// frees the bitmap allocated below - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); -// allocates a large-enough single-channel 8bpp bitmap and renders the -// specified character/glyph at the specified scale into it, with -// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). -// *width & *height are filled out with the width & height of the bitmap, -// which is stored left-to-right, top-to-bottom. -// -// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); -// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel -// shift for the character - -STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); -// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap -// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap -// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the -// width and height and positioning info for it first. - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); -// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel -// shift for the character - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); -// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering -// is performed (see stbtt_PackSetOversampling) - -STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); -// get the bbox of the bitmap centered around the glyph origin; so the -// bitmap width is ix1-ix0, height is iy1-iy0, and location to place -// the bitmap top left is (leftSideBearing*scale,iy0). -// (Note that the bitmap uses y-increases-down, but the shape uses -// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) - -STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); -// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel -// shift for the character - -// the following functions are equivalent to the above functions, but operate -// on glyph indices instead of Unicode codepoints (for efficiency) -STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); -STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); -STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); - - -// @TODO: don't expose this structure -typedef struct -{ - int w,h,stride; - unsigned char *pixels; -} stbtt__bitmap; - -// rasterize a shape with quadratic beziers into a bitmap -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into - float flatness_in_pixels, // allowable error of curve in pixels - stbtt_vertex *vertices, // array of vertices defining shape - int num_verts, // number of vertices in above array - float scale_x, float scale_y, // scale applied to input vertices - float shift_x, float shift_y, // translation applied to input vertices - int x_off, int y_off, // another translation applied to input - int invert, // if non-zero, vertically flip shape - void *userdata); // context for to STBTT_MALLOC - -////////////////////////////////////////////////////////////////////////////// -// -// Signed Distance Function (or Field) rendering - -STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); -// frees the SDF bitmap allocated below - -STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); -// These functions compute a discretized SDF field for a single character, suitable for storing -// in a single-channel texture, sampling with bilinear filtering, and testing against -// larger than some threshold to produce scalable fonts. -// info -- the font -// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap -// glyph/codepoint -- the character to generate the SDF for -// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), -// which allows effects like bit outlines -// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) -// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) -// if positive, > onedge_value is inside; if negative, < onedge_value is inside -// width,height -- output height & width of the SDF bitmap (including padding) -// xoff,yoff -- output origin of the character -// return value -- a 2D array of bytes 0..255, width*height in size -// -// pixel_dist_scale & onedge_value are a scale & bias that allows you to make -// optimal use of the limited 0..255 for your application, trading off precision -// and special effects. SDF values outside the range 0..255 are clamped to 0..255. -// -// Example: -// scale = stbtt_ScaleForPixelHeight(22) -// padding = 5 -// onedge_value = 180 -// pixel_dist_scale = 180/5.0 = 36.0 -// -// This will create an SDF bitmap in which the character is about 22 pixels -// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled -// shape, sample the SDF at each pixel and fill the pixel if the SDF value -// is greater than or equal to 180/255. (You'll actually want to antialias, -// which is beyond the scope of this example.) Additionally, you can compute -// offset outlines (e.g. to stroke the character border inside & outside, -// or only outside). For example, to fill outside the character up to 3 SDF -// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above -// choice of variables maps a range from 5 pixels outside the shape to -// 2 pixels inside the shape to 0..255; this is intended primarily for apply -// outside effects only (the interior range is needed to allow proper -// antialiasing of the font at *smaller* sizes) -// -// The function computes the SDF analytically at each SDF pixel, not by e.g. -// building a higher-res bitmap and approximating it. In theory the quality -// should be as high as possible for an SDF of this size & representation, but -// unclear if this is true in practice (perhaps building a higher-res bitmap -// and computing from that can allow drop-out prevention). -// -// The algorithm has not been optimized at all, so expect it to be slow -// if computing lots of characters or very large sizes. - - - -////////////////////////////////////////////////////////////////////////////// -// -// Finding the right font... -// -// You should really just solve this offline, keep your own tables -// of what font is what, and don't try to get it out of the .ttf file. -// That's because getting it out of the .ttf file is really hard, because -// the names in the file can appear in many possible encodings, in many -// possible languages, and e.g. if you need a case-insensitive comparison, -// the details of that depend on the encoding & language in a complex way -// (actually underspecified in truetype, but also gigantic). -// -// But you can use the provided functions in two possible ways: -// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on -// unicode-encoded names to try to find the font you want; -// you can run this before calling stbtt_InitFont() -// -// stbtt_GetFontNameString() lets you get any of the various strings -// from the file yourself and do your own comparisons on them. -// You have to have called stbtt_InitFont() first. - - -STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); -// returns the offset (not index) of the font that matches, or -1 if none -// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". -// if you use any other flag, use a font name like "Arial"; this checks -// the 'macStyle' header field; i don't know if fonts set this consistently -#define STBTT_MACSTYLE_DONTCARE 0 -#define STBTT_MACSTYLE_BOLD 1 -#define STBTT_MACSTYLE_ITALIC 2 -#define STBTT_MACSTYLE_UNDERSCORE 4 -#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 - -STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); -// returns 1/0 whether the first string interpreted as utf8 is identical to -// the second string interpreted as big-endian utf16... useful for strings from next func - -STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); -// returns the string (which may be big-endian double byte, e.g. for unicode) -// and puts the length in bytes in *length. -// -// some of the values for the IDs are below; for more see the truetype spec: -// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html -// http://www.microsoft.com/typography/otspec/name.htm - -enum { // platformID - STBTT_PLATFORM_ID_UNICODE =0, - STBTT_PLATFORM_ID_MAC =1, - STBTT_PLATFORM_ID_ISO =2, - STBTT_PLATFORM_ID_MICROSOFT =3 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_UNICODE - STBTT_UNICODE_EID_UNICODE_1_0 =0, - STBTT_UNICODE_EID_UNICODE_1_1 =1, - STBTT_UNICODE_EID_ISO_10646 =2, - STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, - STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT - STBTT_MS_EID_SYMBOL =0, - STBTT_MS_EID_UNICODE_BMP =1, - STBTT_MS_EID_SHIFTJIS =2, - STBTT_MS_EID_UNICODE_FULL =10 -}; - -enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes - STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, - STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, - STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, - STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 -}; - -enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... - // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs - STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, - STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, - STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, - STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, - STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, - STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D -}; - -enum { // languageID for STBTT_PLATFORM_ID_MAC - STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, - STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, - STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, - STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , - STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , - STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, - STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 -}; - -#ifdef __cplusplus -} -#endif - -#endif // __STB_INCLUDE_STB_TRUETYPE_H__ - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -//// -//// IMPLEMENTATION -//// -//// - -#ifdef STB_TRUETYPE_IMPLEMENTATION - -#ifndef STBTT_MAX_OVERSAMPLE -#define STBTT_MAX_OVERSAMPLE 8 -#endif - -#if STBTT_MAX_OVERSAMPLE > 255 -#error "STBTT_MAX_OVERSAMPLE cannot be > 255" -#endif - -typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; - -#ifndef STBTT_RASTERIZER_VERSION -#define STBTT_RASTERIZER_VERSION 2 -#endif - -#ifdef _MSC_VER -#define STBTT__NOTUSED(v) (void)(v) -#else -#define STBTT__NOTUSED(v) (void)sizeof(v) -#endif - -////////////////////////////////////////////////////////////////////////// -// -// stbtt__buf helpers to parse data from file -// - -static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) -{ - if (b->cursor >= b->size) - return 0; - return b->data[b->cursor++]; -} - -static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) -{ - if (b->cursor >= b->size) - return 0; - return b->data[b->cursor]; -} - -static void stbtt__buf_seek(stbtt__buf *b, int o) -{ - STBTT_assert(!(o > b->size || o < 0)); - b->cursor = (o > b->size || o < 0) ? b->size : o; -} - -static void stbtt__buf_skip(stbtt__buf *b, int o) -{ - stbtt__buf_seek(b, b->cursor + o); -} - -static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) -{ - stbtt_uint32 v = 0; - int i; - STBTT_assert(n >= 1 && n <= 4); - for (i = 0; i < n; i++) - v = (v << 8) | stbtt__buf_get8(b); - return v; -} - -static stbtt__buf stbtt__new_buf(const void *p, size_t size) -{ - stbtt__buf r; - STBTT_assert(size < 0x40000000); - r.data = (stbtt_uint8*) p; - r.size = (int) size; - r.cursor = 0; - return r; -} - -#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) -#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) - -static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) -{ - stbtt__buf r = stbtt__new_buf(NULL, 0); - if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; - r.data = b->data + o; - r.size = s; - return r; -} - -static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) -{ - int count, start, offsize; - start = b->cursor; - count = stbtt__buf_get16(b); - if (count) { - offsize = stbtt__buf_get8(b); - STBTT_assert(offsize >= 1 && offsize <= 4); - stbtt__buf_skip(b, offsize * count); - stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); - } - return stbtt__buf_range(b, start, b->cursor - start); -} - -static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) -{ - int b0 = stbtt__buf_get8(b); - if (b0 >= 32 && b0 <= 246) return b0 - 139; - else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; - else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; - else if (b0 == 28) return stbtt__buf_get16(b); - else if (b0 == 29) return stbtt__buf_get32(b); - STBTT_assert(0); - return 0; -} - -static void stbtt__cff_skip_operand(stbtt__buf *b) { - int v, b0 = stbtt__buf_peek8(b); - STBTT_assert(b0 >= 28); - if (b0 == 30) { - stbtt__buf_skip(b, 1); - while (b->cursor < b->size) { - v = stbtt__buf_get8(b); - if ((v & 0xF) == 0xF || (v >> 4) == 0xF) - break; - } - } else { - stbtt__cff_int(b); - } -} - -static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) -{ - stbtt__buf_seek(b, 0); - while (b->cursor < b->size) { - int start = b->cursor, end, op; - while (stbtt__buf_peek8(b) >= 28) - stbtt__cff_skip_operand(b); - end = b->cursor; - op = stbtt__buf_get8(b); - if (op == 12) op = stbtt__buf_get8(b) | 0x100; - if (op == key) return stbtt__buf_range(b, start, end-start); - } - return stbtt__buf_range(b, 0, 0); -} - -static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) -{ - int i; - stbtt__buf operands = stbtt__dict_get(b, key); - for (i = 0; i < outcount && operands.cursor < operands.size; i++) - out[i] = stbtt__cff_int(&operands); -} - -static int stbtt__cff_index_count(stbtt__buf *b) -{ - stbtt__buf_seek(b, 0); - return stbtt__buf_get16(b); -} - -static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) -{ - int count, offsize, start, end; - stbtt__buf_seek(&b, 0); - count = stbtt__buf_get16(&b); - offsize = stbtt__buf_get8(&b); - STBTT_assert(i >= 0 && i < count); - STBTT_assert(offsize >= 1 && offsize <= 4); - stbtt__buf_skip(&b, i*offsize); - start = stbtt__buf_get(&b, offsize); - end = stbtt__buf_get(&b, offsize); - return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); -} - -////////////////////////////////////////////////////////////////////////// -// -// accessors to parse data from file -// - -// on platforms that don't allow misaligned reads, if we want to allow -// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE - -#define ttBYTE(p) (* (stbtt_uint8 *) (p)) -#define ttCHAR(p) (* (stbtt_int8 *) (p)) -#define ttFixed(p) ttLONG(p) - -static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } -static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } -static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } -static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - -#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) -#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) - -static int stbtt__isfont(stbtt_uint8 *font) -{ - // check the version number - if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 - if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! - if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF - if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 - if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts - return 0; -} - -// @OPTIMIZE: binary search -static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) -{ - stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); - stbtt_uint32 tabledir = fontstart + 12; - stbtt_int32 i; - for (i=0; i < num_tables; ++i) { - stbtt_uint32 loc = tabledir + 16*i; - if (stbtt_tag(data+loc+0, tag)) - return ttULONG(data+loc+8); - } - return 0; -} - -static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) -{ - // if it's just a font, there's only one valid index - if (stbtt__isfont(font_collection)) - return index == 0 ? 0 : -1; - - // check if it's a TTC - if (stbtt_tag(font_collection, "ttcf")) { - // version 1? - if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { - stbtt_int32 n = ttLONG(font_collection+8); - if (index >= n) - return -1; - return ttULONG(font_collection+12+index*4); - } - } - return -1; -} - -static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) -{ - // if it's just a font, there's only one valid font - if (stbtt__isfont(font_collection)) - return 1; - - // check if it's a TTC - if (stbtt_tag(font_collection, "ttcf")) { - // version 1? - if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { - return ttLONG(font_collection+8); - } - } - return 0; -} - -static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) -{ - stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; - stbtt__buf pdict; - stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); - if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); - pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); - stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); - if (!subrsoff) return stbtt__new_buf(NULL, 0); - stbtt__buf_seek(&cff, private_loc[1]+subrsoff); - return stbtt__cff_get_index(&cff); -} - -// since most people won't use this, find this table the first time it's needed -static int stbtt__get_svg(stbtt_fontinfo *info) -{ - stbtt_uint32 t; - if (info->svg < 0) { - t = stbtt__find_table(info->data, info->fontstart, "SVG "); - if (t) { - stbtt_uint32 offset = ttULONG(info->data + t + 2); - info->svg = t + offset; - } else { - info->svg = 0; - } - } - return info->svg; -} - -static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) -{ - stbtt_uint32 cmap, t; - stbtt_int32 i,numTables; - - info->data = data; - info->fontstart = fontstart; - info->cff = stbtt__new_buf(NULL, 0); - - cmap = stbtt__find_table(data, fontstart, "cmap"); // required - info->loca = stbtt__find_table(data, fontstart, "loca"); // required - info->head = stbtt__find_table(data, fontstart, "head"); // required - info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required - info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required - info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required - info->kern = stbtt__find_table(data, fontstart, "kern"); // not required - info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required - - if (!cmap || !info->head || !info->hhea || !info->hmtx) - return 0; - if (info->glyf) { - // required for truetype - if (!info->loca) return 0; - } else { - // initialization for CFF / Type2 fonts (OTF) - stbtt__buf b, topdict, topdictidx; - stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; - stbtt_uint32 cff; - - cff = stbtt__find_table(data, fontstart, "CFF "); - if (!cff) return 0; - - info->fontdicts = stbtt__new_buf(NULL, 0); - info->fdselect = stbtt__new_buf(NULL, 0); - - // @TODO this should use size from table (not 512MB) - info->cff = stbtt__new_buf(data+cff, 512*1024*1024); - b = info->cff; - - // read the header - stbtt__buf_skip(&b, 2); - stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize - - // @TODO the name INDEX could list multiple fonts, - // but we just use the first one. - stbtt__cff_get_index(&b); // name INDEX - topdictidx = stbtt__cff_get_index(&b); - topdict = stbtt__cff_index_get(topdictidx, 0); - stbtt__cff_get_index(&b); // string INDEX - info->gsubrs = stbtt__cff_get_index(&b); - - stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); - stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); - stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); - stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); - info->subrs = stbtt__get_subrs(b, topdict); - - // we only support Type 2 charstrings - if (cstype != 2) return 0; - if (charstrings == 0) return 0; - - if (fdarrayoff) { - // looks like a CID font - if (!fdselectoff) return 0; - stbtt__buf_seek(&b, fdarrayoff); - info->fontdicts = stbtt__cff_get_index(&b); - info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); - } - - stbtt__buf_seek(&b, charstrings); - info->charstrings = stbtt__cff_get_index(&b); - } - - t = stbtt__find_table(data, fontstart, "maxp"); - if (t) - info->numGlyphs = ttUSHORT(data+t+4); - else - info->numGlyphs = 0xffff; - - info->svg = -1; - - // find a cmap encoding table we understand *now* to avoid searching - // later. (todo: could make this installable) - // the same regardless of glyph. - numTables = ttUSHORT(data + cmap + 2); - info->index_map = 0; - for (i=0; i < numTables; ++i) { - stbtt_uint32 encoding_record = cmap + 4 + 8 * i; - // find an encoding we understand: - switch(ttUSHORT(data+encoding_record)) { - case STBTT_PLATFORM_ID_MICROSOFT: - switch (ttUSHORT(data+encoding_record+2)) { - case STBTT_MS_EID_UNICODE_BMP: - case STBTT_MS_EID_UNICODE_FULL: - // MS/Unicode - info->index_map = cmap + ttULONG(data+encoding_record+4); - break; - } - break; - case STBTT_PLATFORM_ID_UNICODE: - // Mac/iOS has these - // all the encodingIDs are unicode, so we don't bother to check it - info->index_map = cmap + ttULONG(data+encoding_record+4); - break; - } - } - if (info->index_map == 0) - return 0; - - info->indexToLocFormat = ttUSHORT(data+info->head + 50); - return 1; -} - -STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) -{ - stbtt_uint8 *data = info->data; - stbtt_uint32 index_map = info->index_map; - - stbtt_uint16 format = ttUSHORT(data + index_map + 0); - if (format == 0) { // apple byte encoding - stbtt_int32 bytes = ttUSHORT(data + index_map + 2); - if (unicode_codepoint < bytes-6) - return ttBYTE(data + index_map + 6 + unicode_codepoint); - return 0; - } else if (format == 6) { - stbtt_uint32 first = ttUSHORT(data + index_map + 6); - stbtt_uint32 count = ttUSHORT(data + index_map + 8); - if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) - return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); - return 0; - } else if (format == 2) { - STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean - return 0; - } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges - stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; - stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; - stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); - stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; - - // do a binary search of the segments - stbtt_uint32 endCount = index_map + 14; - stbtt_uint32 search = endCount; - - if (unicode_codepoint > 0xffff) - return 0; - - // they lie from endCount .. endCount + segCount - // but searchRange is the nearest power of two, so... - if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) - search += rangeShift*2; - - // now decrement to bias correctly to find smallest - search -= 2; - while (entrySelector) { - stbtt_uint16 end; - searchRange >>= 1; - end = ttUSHORT(data + search + searchRange*2); - if (unicode_codepoint > end) - search += searchRange*2; - --entrySelector; - } - search += 2; - - { - stbtt_uint16 offset, start, last; - stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); - - start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); - last = ttUSHORT(data + endCount + 2*item); - if (unicode_codepoint < start || unicode_codepoint > last) - return 0; - - offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); - if (offset == 0) - return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); - - return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); - } - } else if (format == 12 || format == 13) { - stbtt_uint32 ngroups = ttULONG(data+index_map+12); - stbtt_int32 low,high; - low = 0; high = (stbtt_int32)ngroups; - // Binary search the right group. - while (low < high) { - stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high - stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); - stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); - if ((stbtt_uint32) unicode_codepoint < start_char) - high = mid; - else if ((stbtt_uint32) unicode_codepoint > end_char) - low = mid+1; - else { - stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); - if (format == 12) - return start_glyph + unicode_codepoint-start_char; - else // format == 13 - return start_glyph; - } - } - return 0; // not found - } - // @TODO - STBTT_assert(0); - return 0; -} - -STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) -{ - return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); -} - -static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) -{ - v->type = type; - v->x = (stbtt_int16) x; - v->y = (stbtt_int16) y; - v->cx = (stbtt_int16) cx; - v->cy = (stbtt_int16) cy; -} - -static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) -{ - int g1,g2; - - STBTT_assert(!info->cff.size); - - if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range - if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format - - if (info->indexToLocFormat == 0) { - g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; - g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; - } else { - g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); - g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); - } - - return g1==g2 ? -1 : g1; // if length is 0, return -1 -} - -static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); - -STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) -{ - if (info->cff.size) { - stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); - } else { - int g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 0; - - if (x0) *x0 = ttSHORT(info->data + g + 2); - if (y0) *y0 = ttSHORT(info->data + g + 4); - if (x1) *x1 = ttSHORT(info->data + g + 6); - if (y1) *y1 = ttSHORT(info->data + g + 8); - } - return 1; -} - -STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) -{ - return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); -} - -STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) -{ - stbtt_int16 numberOfContours; - int g; - if (info->cff.size) - return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; - g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 1; - numberOfContours = ttSHORT(info->data + g); - return numberOfContours == 0; -} - -static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, - stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) -{ - if (start_off) { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); - } else { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); - else - stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); - } - return num_vertices; -} - -static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) -{ - stbtt_int16 numberOfContours; - stbtt_uint8 *endPtsOfContours; - stbtt_uint8 *data = info->data; - stbtt_vertex *vertices=0; - int num_vertices=0; - int g = stbtt__GetGlyfOffset(info, glyph_index); - - *pvertices = NULL; - - if (g < 0) return 0; - - numberOfContours = ttSHORT(data + g); - - if (numberOfContours > 0) { - stbtt_uint8 flags=0,flagcount; - stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; - stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; - stbtt_uint8 *points; - endPtsOfContours = (data + g + 10); - ins = ttUSHORT(data + g + 10 + numberOfContours * 2); - points = data + g + 10 + numberOfContours * 2 + 2 + ins; - - n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); - - m = n + 2*numberOfContours; // a loose bound on how many vertices we might need - vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); - if (vertices == 0) - return 0; - - next_move = 0; - flagcount=0; - - // in first pass, we load uninterpreted data into the allocated array - // above, shifted to the end of the array so we won't overwrite it when - // we create our final data starting from the front - - off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated - - // first load flags - - for (i=0; i < n; ++i) { - if (flagcount == 0) { - flags = *points++; - if (flags & 8) - flagcount = *points++; - } else - --flagcount; - vertices[off+i].type = flags; - } - - // now load x coordinates - x=0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - if (flags & 2) { - stbtt_int16 dx = *points++; - x += (flags & 16) ? dx : -dx; // ??? - } else { - if (!(flags & 16)) { - x = x + (stbtt_int16) (points[0]*256 + points[1]); - points += 2; - } - } - vertices[off+i].x = (stbtt_int16) x; - } - - // now load y coordinates - y=0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - if (flags & 4) { - stbtt_int16 dy = *points++; - y += (flags & 32) ? dy : -dy; // ??? - } else { - if (!(flags & 32)) { - y = y + (stbtt_int16) (points[0]*256 + points[1]); - points += 2; - } - } - vertices[off+i].y = (stbtt_int16) y; - } - - // now convert them to our format - num_vertices=0; - sx = sy = cx = cy = scx = scy = 0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - x = (stbtt_int16) vertices[off+i].x; - y = (stbtt_int16) vertices[off+i].y; - - if (next_move == i) { - if (i != 0) - num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - - // now start the new one - start_off = !(flags & 1); - if (start_off) { - // if we start off with an off-curve point, then when we need to find a point on the curve - // where we can start, and we need to save some state for when we wraparound. - scx = x; - scy = y; - if (!(vertices[off+i+1].type & 1)) { - // next point is also a curve point, so interpolate an on-point curve - sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; - sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; - } else { - // otherwise just use the next point as our start point - sx = (stbtt_int32) vertices[off+i+1].x; - sy = (stbtt_int32) vertices[off+i+1].y; - ++i; // we're using point i+1 as the starting point, so skip it - } - } else { - sx = x; - sy = y; - } - stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); - was_off = 0; - next_move = 1 + ttUSHORT(endPtsOfContours+j*2); - ++j; - } else { - if (!(flags & 1)) { // if it's a curve - if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); - cx = x; - cy = y; - was_off = 1; - } else { - if (was_off) - stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); - else - stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); - was_off = 0; - } - } - } - num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - } else if (numberOfContours < 0) { - // Compound shapes. - int more = 1; - stbtt_uint8 *comp = data + g + 10; - num_vertices = 0; - vertices = 0; - while (more) { - stbtt_uint16 flags, gidx; - int comp_num_verts = 0, i; - stbtt_vertex *comp_verts = 0, *tmp = 0; - float mtx[6] = {1,0,0,1,0,0}, m, n; - - flags = ttSHORT(comp); comp+=2; - gidx = ttSHORT(comp); comp+=2; - - if (flags & 2) { // XY values - if (flags & 1) { // shorts - mtx[4] = ttSHORT(comp); comp+=2; - mtx[5] = ttSHORT(comp); comp+=2; - } else { - mtx[4] = ttCHAR(comp); comp+=1; - mtx[5] = ttCHAR(comp); comp+=1; - } - } - else { - // @TODO handle matching point - STBTT_assert(0); - } - if (flags & (1<<3)) { // WE_HAVE_A_SCALE - mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE - mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO - mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; - mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; - } - - // Find transformation scales. - m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); - n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); - - // Get indexed glyph. - comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); - if (comp_num_verts > 0) { - // Transform vertices. - for (i = 0; i < comp_num_verts; ++i) { - stbtt_vertex* v = &comp_verts[i]; - stbtt_vertex_type x,y; - x=v->x; y=v->y; - v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - x=v->cx; y=v->cy; - v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - } - // Append vertices. - tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); - if (!tmp) { - if (vertices) STBTT_free(vertices, info->userdata); - if (comp_verts) STBTT_free(comp_verts, info->userdata); - return 0; - } - if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); - STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); - if (vertices) STBTT_free(vertices, info->userdata); - vertices = tmp; - STBTT_free(comp_verts, info->userdata); - num_vertices += comp_num_verts; - } - // More components ? - more = flags & (1<<5); - } - } else { - // numberOfCounters == 0, do nothing - } - - *pvertices = vertices; - return num_vertices; -} - -typedef struct -{ - int bounds; - int started; - float first_x, first_y; - float x, y; - stbtt_int32 min_x, max_x, min_y, max_y; - - stbtt_vertex *pvertices; - int num_vertices; -} stbtt__csctx; - -#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} - -static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) -{ - if (x > c->max_x || !c->started) c->max_x = x; - if (y > c->max_y || !c->started) c->max_y = y; - if (x < c->min_x || !c->started) c->min_x = x; - if (y < c->min_y || !c->started) c->min_y = y; - c->started = 1; -} - -static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) -{ - if (c->bounds) { - stbtt__track_vertex(c, x, y); - if (type == STBTT_vcubic) { - stbtt__track_vertex(c, cx, cy); - stbtt__track_vertex(c, cx1, cy1); - } - } else { - stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); - c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; - c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; - } - c->num_vertices++; -} - -static void stbtt__csctx_close_shape(stbtt__csctx *ctx) -{ - if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) - stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); -} - -static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) -{ - stbtt__csctx_close_shape(ctx); - ctx->first_x = ctx->x = ctx->x + dx; - ctx->first_y = ctx->y = ctx->y + dy; - stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); -} - -static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) -{ - ctx->x += dx; - ctx->y += dy; - stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); -} - -static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) -{ - float cx1 = ctx->x + dx1; - float cy1 = ctx->y + dy1; - float cx2 = cx1 + dx2; - float cy2 = cy1 + dy2; - ctx->x = cx2 + dx3; - ctx->y = cy2 + dy3; - stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); -} - -static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) -{ - int count = stbtt__cff_index_count(&idx); - int bias = 107; - if (count >= 33900) - bias = 32768; - else if (count >= 1240) - bias = 1131; - n += bias; - if (n < 0 || n >= count) - return stbtt__new_buf(NULL, 0); - return stbtt__cff_index_get(idx, n); -} - -static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) -{ - stbtt__buf fdselect = info->fdselect; - int nranges, start, end, v, fmt, fdselector = -1, i; - - stbtt__buf_seek(&fdselect, 0); - fmt = stbtt__buf_get8(&fdselect); - if (fmt == 0) { - // untested - stbtt__buf_skip(&fdselect, glyph_index); - fdselector = stbtt__buf_get8(&fdselect); - } else if (fmt == 3) { - nranges = stbtt__buf_get16(&fdselect); - start = stbtt__buf_get16(&fdselect); - for (i = 0; i < nranges; i++) { - v = stbtt__buf_get8(&fdselect); - end = stbtt__buf_get16(&fdselect); - if (glyph_index >= start && glyph_index < end) { - fdselector = v; - break; - } - start = end; - } - } - if (fdselector == -1) stbtt__new_buf(NULL, 0); - return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); -} - -static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) -{ - int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; - int has_subrs = 0, clear_stack; - float s[48]; - stbtt__buf subr_stack[10], subrs = info->subrs, b; - float f; - -#define STBTT__CSERR(s) (0) - - // this currently ignores the initial width value, which isn't needed if we have hmtx - b = stbtt__cff_index_get(info->charstrings, glyph_index); - while (b.cursor < b.size) { - i = 0; - clear_stack = 1; - b0 = stbtt__buf_get8(&b); - switch (b0) { - // @TODO implement hinting - case 0x13: // hintmask - case 0x14: // cntrmask - if (in_header) - maskbits += (sp / 2); // implicit "vstem" - in_header = 0; - stbtt__buf_skip(&b, (maskbits + 7) / 8); - break; - - case 0x01: // hstem - case 0x03: // vstem - case 0x12: // hstemhm - case 0x17: // vstemhm - maskbits += (sp / 2); - break; - - case 0x15: // rmoveto - in_header = 0; - if (sp < 2) return STBTT__CSERR("rmoveto stack"); - stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); - break; - case 0x04: // vmoveto - in_header = 0; - if (sp < 1) return STBTT__CSERR("vmoveto stack"); - stbtt__csctx_rmove_to(c, 0, s[sp-1]); - break; - case 0x16: // hmoveto - in_header = 0; - if (sp < 1) return STBTT__CSERR("hmoveto stack"); - stbtt__csctx_rmove_to(c, s[sp-1], 0); - break; - - case 0x05: // rlineto - if (sp < 2) return STBTT__CSERR("rlineto stack"); - for (; i + 1 < sp; i += 2) - stbtt__csctx_rline_to(c, s[i], s[i+1]); - break; - - // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical - // starting from a different place. - - case 0x07: // vlineto - if (sp < 1) return STBTT__CSERR("vlineto stack"); - goto vlineto; - case 0x06: // hlineto - if (sp < 1) return STBTT__CSERR("hlineto stack"); - for (;;) { - if (i >= sp) break; - stbtt__csctx_rline_to(c, s[i], 0); - i++; - vlineto: - if (i >= sp) break; - stbtt__csctx_rline_to(c, 0, s[i]); - i++; - } - break; - - case 0x1F: // hvcurveto - if (sp < 4) return STBTT__CSERR("hvcurveto stack"); - goto hvcurveto; - case 0x1E: // vhcurveto - if (sp < 4) return STBTT__CSERR("vhcurveto stack"); - for (;;) { - if (i + 3 >= sp) break; - stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); - i += 4; - hvcurveto: - if (i + 3 >= sp) break; - stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); - i += 4; - } - break; - - case 0x08: // rrcurveto - if (sp < 6) return STBTT__CSERR("rcurveline stack"); - for (; i + 5 < sp; i += 6) - stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); - break; - - case 0x18: // rcurveline - if (sp < 8) return STBTT__CSERR("rcurveline stack"); - for (; i + 5 < sp - 2; i += 6) - stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); - if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); - stbtt__csctx_rline_to(c, s[i], s[i+1]); - break; - - case 0x19: // rlinecurve - if (sp < 8) return STBTT__CSERR("rlinecurve stack"); - for (; i + 1 < sp - 6; i += 2) - stbtt__csctx_rline_to(c, s[i], s[i+1]); - if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); - stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); - break; - - case 0x1A: // vvcurveto - case 0x1B: // hhcurveto - if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); - f = 0.0; - if (sp & 1) { f = s[i]; i++; } - for (; i + 3 < sp; i += 4) { - if (b0 == 0x1B) - stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); - else - stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); - f = 0.0; - } - break; - - case 0x0A: // callsubr - if (!has_subrs) { - if (info->fdselect.size) - subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); - has_subrs = 1; - } - // FALLTHROUGH - case 0x1D: // callgsubr - if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); - v = (int) s[--sp]; - if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); - subr_stack[subr_stack_height++] = b; - b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); - if (b.size == 0) return STBTT__CSERR("subr not found"); - b.cursor = 0; - clear_stack = 0; - break; - - case 0x0B: // return - if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); - b = subr_stack[--subr_stack_height]; - clear_stack = 0; - break; - - case 0x0E: // endchar - stbtt__csctx_close_shape(c); - return 1; - - case 0x0C: { // two-byte escape - float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; - float dx, dy; - int b1 = stbtt__buf_get8(&b); - switch (b1) { - // @TODO These "flex" implementations ignore the flex-depth and resolution, - // and always draw beziers. - case 0x22: // hflex - if (sp < 7) return STBTT__CSERR("hflex stack"); - dx1 = s[0]; - dx2 = s[1]; - dy2 = s[2]; - dx3 = s[3]; - dx4 = s[4]; - dx5 = s[5]; - dx6 = s[6]; - stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); - stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); - break; - - case 0x23: // flex - if (sp < 13) return STBTT__CSERR("flex stack"); - dx1 = s[0]; - dy1 = s[1]; - dx2 = s[2]; - dy2 = s[3]; - dx3 = s[4]; - dy3 = s[5]; - dx4 = s[6]; - dy4 = s[7]; - dx5 = s[8]; - dy5 = s[9]; - dx6 = s[10]; - dy6 = s[11]; - //fd is s[12] - stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); - stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); - break; - - case 0x24: // hflex1 - if (sp < 9) return STBTT__CSERR("hflex1 stack"); - dx1 = s[0]; - dy1 = s[1]; - dx2 = s[2]; - dy2 = s[3]; - dx3 = s[4]; - dx4 = s[5]; - dx5 = s[6]; - dy5 = s[7]; - dx6 = s[8]; - stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); - stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); - break; - - case 0x25: // flex1 - if (sp < 11) return STBTT__CSERR("flex1 stack"); - dx1 = s[0]; - dy1 = s[1]; - dx2 = s[2]; - dy2 = s[3]; - dx3 = s[4]; - dy3 = s[5]; - dx4 = s[6]; - dy4 = s[7]; - dx5 = s[8]; - dy5 = s[9]; - dx6 = dy6 = s[10]; - dx = dx1+dx2+dx3+dx4+dx5; - dy = dy1+dy2+dy3+dy4+dy5; - if (STBTT_fabs(dx) > STBTT_fabs(dy)) - dy6 = -dy; - else - dx6 = -dx; - stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); - stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); - break; - - default: - return STBTT__CSERR("unimplemented"); - } - } break; - - default: - if (b0 != 255 && b0 != 28 && b0 < 32) - return STBTT__CSERR("reserved operator"); - - // push immediate - if (b0 == 255) { - f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; - } else { - stbtt__buf_skip(&b, -1); - f = (float)(stbtt_int16)stbtt__cff_int(&b); - } - if (sp >= 48) return STBTT__CSERR("push stack overflow"); - s[sp++] = f; - clear_stack = 0; - break; - } - if (clear_stack) sp = 0; - } - return STBTT__CSERR("no endchar"); - -#undef STBTT__CSERR -} - -static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) -{ - // runs the charstring twice, once to count and once to output (to avoid realloc) - stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); - stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); - if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { - *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); - output_ctx.pvertices = *pvertices; - if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { - STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); - return output_ctx.num_vertices; - } - } - *pvertices = NULL; - return 0; -} - -static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) -{ - stbtt__csctx c = STBTT__CSCTX_INIT(1); - int r = stbtt__run_charstring(info, glyph_index, &c); - if (x0) *x0 = r ? c.min_x : 0; - if (y0) *y0 = r ? c.min_y : 0; - if (x1) *x1 = r ? c.max_x : 0; - if (y1) *y1 = r ? c.max_y : 0; - return r ? c.num_vertices : 0; -} - -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) -{ - if (!info->cff.size) - return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); - else - return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); -} - -STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) -{ - stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); - if (glyph_index < numOfLongHorMetrics) { - if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); - if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); - } else { - if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); - if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); - } -} - -STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) -{ - stbtt_uint8 *data = info->data + info->kern; - - // we only look at the first table. it must be 'horizontal' and format 0. - if (!info->kern) - return 0; - if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 - return 0; - if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format - return 0; - - return ttUSHORT(data+10); -} - -STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) -{ - stbtt_uint8 *data = info->data + info->kern; - int k, length; - - // we only look at the first table. it must be 'horizontal' and format 0. - if (!info->kern) - return 0; - if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 - return 0; - if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format - return 0; - - length = ttUSHORT(data+10); - if (table_length < length) - length = table_length; - - for (k = 0; k < length; k++) - { - table[k].glyph1 = ttUSHORT(data+18+(k*6)); - table[k].glyph2 = ttUSHORT(data+20+(k*6)); - table[k].advance = ttSHORT(data+22+(k*6)); - } - - return length; -} - -static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) -{ - stbtt_uint8 *data = info->data + info->kern; - stbtt_uint32 needle, straw; - int l, r, m; - - // we only look at the first table. it must be 'horizontal' and format 0. - if (!info->kern) - return 0; - if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 - return 0; - if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format - return 0; - - l = 0; - r = ttUSHORT(data+10) - 1; - needle = glyph1 << 16 | glyph2; - while (l <= r) { - m = (l + r) >> 1; - straw = ttULONG(data+18+(m*6)); // note: unaligned read - if (needle < straw) - r = m - 1; - else if (needle > straw) - l = m + 1; - else - return ttSHORT(data+22+(m*6)); - } - return 0; -} - -static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) -{ - stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); - switch (coverageFormat) { - case 1: { - stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); - - // Binary search. - stbtt_int32 l=0, r=glyphCount-1, m; - int straw, needle=glyph; - while (l <= r) { - stbtt_uint8 *glyphArray = coverageTable + 4; - stbtt_uint16 glyphID; - m = (l + r) >> 1; - glyphID = ttUSHORT(glyphArray + 2 * m); - straw = glyphID; - if (needle < straw) - r = m - 1; - else if (needle > straw) - l = m + 1; - else { - return m; - } - } - break; - } - - case 2: { - stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); - stbtt_uint8 *rangeArray = coverageTable + 4; - - // Binary search. - stbtt_int32 l=0, r=rangeCount-1, m; - int strawStart, strawEnd, needle=glyph; - while (l <= r) { - stbtt_uint8 *rangeRecord; - m = (l + r) >> 1; - rangeRecord = rangeArray + 6 * m; - strawStart = ttUSHORT(rangeRecord); - strawEnd = ttUSHORT(rangeRecord + 2); - if (needle < strawStart) - r = m - 1; - else if (needle > strawEnd) - l = m + 1; - else { - stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); - return startCoverageIndex + glyph - strawStart; - } - } - break; - } - - default: return -1; // unsupported - } - - return -1; -} - -static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) -{ - stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); - switch (classDefFormat) - { - case 1: { - stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); - stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); - stbtt_uint8 *classDef1ValueArray = classDefTable + 6; - - if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) - return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); - break; - } - - case 2: { - stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); - stbtt_uint8 *classRangeRecords = classDefTable + 4; - - // Binary search. - stbtt_int32 l=0, r=classRangeCount-1, m; - int strawStart, strawEnd, needle=glyph; - while (l <= r) { - stbtt_uint8 *classRangeRecord; - m = (l + r) >> 1; - classRangeRecord = classRangeRecords + 6 * m; - strawStart = ttUSHORT(classRangeRecord); - strawEnd = ttUSHORT(classRangeRecord + 2); - if (needle < strawStart) - r = m - 1; - else if (needle > strawEnd) - l = m + 1; - else - return (stbtt_int32)ttUSHORT(classRangeRecord + 4); - } - break; - } - - default: - return -1; // Unsupported definition type, return an error. - } - - // "All glyphs not assigned to a class fall into class 0". (OpenType spec) - return 0; -} - -// Define to STBTT_assert(x) if you want to break on unimplemented formats. -#define STBTT_GPOS_TODO_assert(x) - -static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) -{ - stbtt_uint16 lookupListOffset; - stbtt_uint8 *lookupList; - stbtt_uint16 lookupCount; - stbtt_uint8 *data; - stbtt_int32 i, sti; - - if (!info->gpos) return 0; - - data = info->data + info->gpos; - - if (ttUSHORT(data+0) != 1) return 0; // Major version 1 - if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 - - lookupListOffset = ttUSHORT(data+8); - lookupList = data + lookupListOffset; - lookupCount = ttUSHORT(lookupList); - - for (i=0; i= pairSetCount) return 0; - - needle=glyph2; - r=pairValueCount-1; - l=0; - - // Binary search. - while (l <= r) { - stbtt_uint16 secondGlyph; - stbtt_uint8 *pairValue; - m = (l + r) >> 1; - pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; - secondGlyph = ttUSHORT(pairValue); - straw = secondGlyph; - if (needle < straw) - r = m - 1; - else if (needle > straw) - l = m + 1; - else { - stbtt_int16 xAdvance = ttSHORT(pairValue + 2); - return xAdvance; - } - } - } else - return 0; - break; - } - - case 2: { - stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); - stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); - if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? - stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); - stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); - int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); - int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); - - stbtt_uint16 class1Count = ttUSHORT(table + 12); - stbtt_uint16 class2Count = ttUSHORT(table + 14); - stbtt_uint8 *class1Records, *class2Records; - stbtt_int16 xAdvance; - - if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed - if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed - - class1Records = table + 16; - class2Records = class1Records + 2 * (glyph1class * class2Count); - xAdvance = ttSHORT(class2Records + 2 * glyph2class); - return xAdvance; - } else - return 0; - break; - } - - default: - return 0; // Unsupported position format - } - } - } - - return 0; -} - -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) -{ - int xAdvance = 0; - - if (info->gpos) - xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); - else if (info->kern) - xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); - - return xAdvance; -} - -STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) -{ - if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs - return 0; - return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); -} - -STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) -{ - stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); -} - -STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) -{ - if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); - if (descent) *descent = ttSHORT(info->data+info->hhea + 6); - if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); -} - -STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) -{ - int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); - if (!tab) - return 0; - if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); - if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); - if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); - return 1; -} - -STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) -{ - *x0 = ttSHORT(info->data + info->head + 36); - *y0 = ttSHORT(info->data + info->head + 38); - *x1 = ttSHORT(info->data + info->head + 40); - *y1 = ttSHORT(info->data + info->head + 42); -} - -STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) -{ - int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); - return (float) height / fheight; -} - -STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) -{ - int unitsPerEm = ttUSHORT(info->data + info->head + 18); - return pixels / unitsPerEm; -} - -STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) -{ - STBTT_free(v, info->userdata); -} - -STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) -{ - int i; - stbtt_uint8 *data = info->data; - stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); - - int numEntries = ttUSHORT(svg_doc_list); - stbtt_uint8 *svg_docs = svg_doc_list + 2; - - for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) - return svg_doc; - } - return 0; -} - -STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) -{ - stbtt_uint8 *data = info->data; - stbtt_uint8 *svg_doc; - - if (info->svg == 0) - return 0; - - svg_doc = stbtt_FindSVGDoc(info, gl); - if (svg_doc != NULL) { - *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); - return ttULONG(svg_doc + 8); - } else { - return 0; - } -} - -STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) -{ - return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); -} - -////////////////////////////////////////////////////////////////////////////// -// -// antialiasing software rasterizer -// - -STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning - if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { - // e.g. space character - if (ix0) *ix0 = 0; - if (iy0) *iy0 = 0; - if (ix1) *ix1 = 0; - if (iy1) *iy1 = 0; - } else { - // move to integral bboxes (treating pixels as little squares, what pixels get touched)? - if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); - if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); - if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); - if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); - } -} - -STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); -} - -STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); -} - -STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); -} - -////////////////////////////////////////////////////////////////////////////// -// -// Rasterizer - -typedef struct stbtt__hheap_chunk -{ - struct stbtt__hheap_chunk *next; -} stbtt__hheap_chunk; - -typedef struct stbtt__hheap -{ - struct stbtt__hheap_chunk *head; - void *first_free; - int num_remaining_in_head_chunk; -} stbtt__hheap; - -static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) -{ - if (hh->first_free) { - void *p = hh->first_free; - hh->first_free = * (void **) p; - return p; - } else { - if (hh->num_remaining_in_head_chunk == 0) { - int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); - stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); - if (c == NULL) - return NULL; - c->next = hh->head; - hh->head = c; - hh->num_remaining_in_head_chunk = count; - } - --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; - } -} - -static void stbtt__hheap_free(stbtt__hheap *hh, void *p) -{ - *(void **) p = hh->first_free; - hh->first_free = p; -} - -static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) -{ - stbtt__hheap_chunk *c = hh->head; - while (c) { - stbtt__hheap_chunk *n = c->next; - STBTT_free(c, userdata); - c = n; - } -} - -typedef struct stbtt__edge { - float x0,y0, x1,y1; - int invert; -} stbtt__edge; - - -typedef struct stbtt__active_edge -{ - struct stbtt__active_edge *next; - #if STBTT_RASTERIZER_VERSION==1 - int x,dx; - float ey; - int direction; - #elif STBTT_RASTERIZER_VERSION==2 - float fx,fdx,fdy; - float direction; - float sy; - float ey; - #else - #error "Unrecognized value of STBTT_RASTERIZER_VERSION" - #endif -} stbtt__active_edge; - -#if STBTT_RASTERIZER_VERSION == 1 -#define STBTT_FIXSHIFT 10 -#define STBTT_FIX (1 << STBTT_FIXSHIFT) -#define STBTT_FIXMASK (STBTT_FIX-1) - -static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) -{ - stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); - float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); - STBTT_assert(z != NULL); - if (!z) return z; - - // round dx down to avoid overshooting - if (dxdy < 0) - z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); - else - z->dx = STBTT_ifloor(STBTT_FIX * dxdy); - - z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount - z->x -= off_x * STBTT_FIX; - - z->ey = e->y1; - z->next = 0; - z->direction = e->invert ? 1 : -1; - return z; -} -#elif STBTT_RASTERIZER_VERSION == 2 -static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) -{ - stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); - float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); - STBTT_assert(z != NULL); - //STBTT_assert(e->y0 <= start_point); - if (!z) return z; - z->fdx = dxdy; - z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; - z->fx = e->x0 + dxdy * (start_point - e->y0); - z->fx -= off_x; - z->direction = e->invert ? 1.0f : -1.0f; - z->sy = e->y0; - z->ey = e->y1; - z->next = 0; - return z; -} -#else -#error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif - -#if STBTT_RASTERIZER_VERSION == 1 -// note: this routine clips fills that extend off the edges... ideally this -// wouldn't happen, but it could happen if the truetype glyph bounding boxes -// are wrong, or if the user supplies a too-small bitmap -static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) -{ - // non-zero winding fill - int x0=0, w=0; - - while (e) { - if (w == 0) { - // if we're currently at zero, we need to record the edge start point - x0 = e->x; w += e->direction; - } else { - int x1 = e->x; w += e->direction; - // if we went to zero, we need to draw - if (w == 0) { - int i = x0 >> STBTT_FIXSHIFT; - int j = x1 >> STBTT_FIXSHIFT; - - if (i < len && j >= 0) { - if (i == j) { - // x0,x1 are the same pixel, so compute combined coverage - scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); - } else { - if (i >= 0) // add antialiasing for x0 - scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); - else - i = -1; // clip - - if (j < len) // add antialiasing for x1 - scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); - else - j = len; // clip - - for (++i; i < j; ++i) // fill pixels between x0 and x1 - scanline[i] = scanline[i] + (stbtt_uint8) max_weight; - } - } - } - } - - e = e->next; - } -} - -static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) -{ - stbtt__hheap hh = { 0, 0, 0 }; - stbtt__active_edge *active = NULL; - int y,j=0; - int max_weight = (255 / vsubsample); // weight per vertical scanline - int s; // vertical subsample index - unsigned char scanline_data[512], *scanline; - - if (result->w > 512) - scanline = (unsigned char *) STBTT_malloc(result->w, userdata); - else - scanline = scanline_data; - - y = off_y * vsubsample; - e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; - - while (j < result->h) { - STBTT_memset(scanline, 0, result->w); - for (s=0; s < vsubsample; ++s) { - // find center of pixel for this scanline - float scan_y = y + 0.5f; - stbtt__active_edge **step = &active; - - // update all active edges; - // remove all active edges that terminate before the center of this scanline - while (*step) { - stbtt__active_edge * z = *step; - if (z->ey <= scan_y) { - *step = z->next; // delete from list - STBTT_assert(z->direction); - z->direction = 0; - stbtt__hheap_free(&hh, z); - } else { - z->x += z->dx; // advance to position for current scanline - step = &((*step)->next); // advance through list - } - } - - // resort the list if needed - for(;;) { - int changed=0; - step = &active; - while (*step && (*step)->next) { - if ((*step)->x > (*step)->next->x) { - stbtt__active_edge *t = *step; - stbtt__active_edge *q = t->next; - - t->next = q->next; - q->next = t; - *step = q; - changed = 1; - } - step = &(*step)->next; - } - if (!changed) break; - } - - // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline - while (e->y0 <= scan_y) { - if (e->y1 > scan_y) { - stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); - if (z != NULL) { - // find insertion point - if (active == NULL) - active = z; - else if (z->x < active->x) { - // insert at front - z->next = active; - active = z; - } else { - // find thing to insert AFTER - stbtt__active_edge *p = active; - while (p->next && p->next->x < z->x) - p = p->next; - // at this point, p->next->x is NOT < z->x - z->next = p->next; - p->next = z; - } - } - } - ++e; - } - - // now process all active edges in XOR fashion - if (active) - stbtt__fill_active_edges(scanline, result->w, active, max_weight); - - ++y; - } - STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); - ++j; - } - - stbtt__hheap_cleanup(&hh, userdata); - - if (scanline != scanline_data) - STBTT_free(scanline, userdata); -} - -#elif STBTT_RASTERIZER_VERSION == 2 - -// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 -// (i.e. it has already been clipped to those) -static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) -{ - if (y0 == y1) return; - STBTT_assert(y0 < y1); - STBTT_assert(e->sy <= e->ey); - if (y0 > e->ey) return; - if (y1 < e->sy) return; - if (y0 < e->sy) { - x0 += (x1-x0) * (e->sy - y0) / (y1-y0); - y0 = e->sy; - } - if (y1 > e->ey) { - x1 += (x1-x0) * (e->ey - y1) / (y1-y0); - y1 = e->ey; - } - - if (x0 == x) - STBTT_assert(x1 <= x+1); - else if (x0 == x+1) - STBTT_assert(x1 >= x); - else if (x0 <= x) - STBTT_assert(x1 <= x); - else if (x0 >= x+1) - STBTT_assert(x1 >= x+1); - else - STBTT_assert(x1 >= x && x1 <= x+1); - - if (x0 <= x && x1 <= x) - scanline[x] += e->direction * (y1-y0); - else if (x0 >= x+1 && x1 >= x+1) - ; - else { - STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); - scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position - } -} - -static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) -{ - STBTT_assert(top_width >= 0); - STBTT_assert(bottom_width >= 0); - return (top_width + bottom_width) / 2.0f * height; -} - -static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) -{ - return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); -} - -static float stbtt__sized_triangle_area(float height, float width) -{ - return height * width / 2; -} - -static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) -{ - float y_bottom = y_top+1; - - while (e) { - // brute force every pixel - - // compute intersection points with top & bottom - STBTT_assert(e->ey >= y_top); - - if (e->fdx == 0) { - float x0 = e->fx; - if (x0 < len) { - if (x0 >= 0) { - stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); - stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); - } else { - stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); - } - } - } else { - float x0 = e->fx; - float dx = e->fdx; - float xb = x0 + dx; - float x_top, x_bottom; - float sy0,sy1; - float dy = e->fdy; - STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); - - // compute endpoints of line segment clipped to this scanline (if the - // line segment starts on this scanline. x0 is the intersection of the - // line with y_top, but that may be off the line segment. - if (e->sy > y_top) { - x_top = x0 + dx * (e->sy - y_top); - sy0 = e->sy; - } else { - x_top = x0; - sy0 = y_top; - } - if (e->ey < y_bottom) { - x_bottom = x0 + dx * (e->ey - y_top); - sy1 = e->ey; - } else { - x_bottom = xb; - sy1 = y_bottom; - } - - if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { - // from here on, we don't have to range check x values - - if ((int) x_top == (int) x_bottom) { - float height; - // simple case, only spans one pixel - int x = (int) x_top; - height = (sy1 - sy0) * e->direction; - STBTT_assert(x >= 0 && x < len); - scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); - scanline_fill[x] += height; // everything right of this pixel is filled - } else { - int x,x1,x2; - float y_crossing, y_final, step, sign, area; - // covers 2+ pixels - if (x_top > x_bottom) { - // flip scanline vertically; signed area is the same - float t; - sy0 = y_bottom - (sy0 - y_top); - sy1 = y_bottom - (sy1 - y_top); - t = sy0, sy0 = sy1, sy1 = t; - t = x_bottom, x_bottom = x_top, x_top = t; - dx = -dx; - dy = -dy; - t = x0, x0 = xb, xb = t; - } - STBTT_assert(dy >= 0); - STBTT_assert(dx >= 0); - - x1 = (int) x_top; - x2 = (int) x_bottom; - // compute intersection with y axis at x1+1 - y_crossing = y_top + dy * (x1+1 - x0); - - // compute intersection with y axis at x2 - y_final = y_top + dy * (x2 - x0); - - // x1 x_top x2 x_bottom - // y_top +------|-----+------------+------------+--------|---+------------+ - // | | | | | | - // | | | | | | - // sy0 | Txxxxx|............|............|............|............| - // y_crossing | *xxxxx.......|............|............|............| - // | | xxxxx..|............|............|............| - // | | /- xx*xxxx........|............|............| - // | | dy < | xxxxxx..|............|............| - // y_final | | \- | xx*xxx.........|............| - // sy1 | | | | xxxxxB...|............| - // | | | | | | - // | | | | | | - // y_bottom +------------+------------+------------+------------+------------+ - // - // goal is to measure the area covered by '.' in each pixel - - // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 - // @TODO: maybe test against sy1 rather than y_bottom? - if (y_crossing > y_bottom) - y_crossing = y_bottom; - - sign = e->direction; - - // area of the rectangle covered from sy0..y_crossing - area = sign * (y_crossing-sy0); - - // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) - scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); - - // check if final y_crossing is blown up; no test case for this - if (y_final > y_bottom) { - y_final = y_bottom; - dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom - } - - // in second pixel, area covered by line segment found in first pixel - // is always a rectangle 1 wide * the height of that line segment; this - // is exactly what the variable 'area' stores. it also gets a contribution - // from the line segment within it. the THIRD pixel will get the first - // pixel's rectangle contribution, the second pixel's rectangle contribution, - // and its own contribution. the 'own contribution' is the same in every pixel except - // the leftmost and rightmost, a trapezoid that slides down in each pixel. - // the second pixel's contribution to the third pixel will be the - // rectangle 1 wide times the height change in the second pixel, which is dy. - - step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x, - // which multiplied by 1-pixel-width is how much pixel area changes for each step in x - // so the area advances by 'step' every time - - for (x = x1+1; x < x2; ++x) { - scanline[x] += area + step/2; // area of trapezoid is 1*step/2 - area += step; - } - STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down - STBTT_assert(sy1 > y_final-0.01f); - - // area covered in the last pixel is the rectangle from all the pixels to the left, - // plus the trapezoid filled by the line segment in this pixel all the way to the right edge - scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); - - // the rest of the line is filled based on the total height of the line segment in this pixel - scanline_fill[x2] += sign * (sy1-sy0); - } - } else { - // if edge goes outside of box we're drawing, we require - // clipping logic. since this does not match the intended use - // of this library, we use a different, very slow brute - // force implementation - // note though that this does happen some of the time because - // x_top and x_bottom can be extrapolated at the top & bottom of - // the shape and actually lie outside the bounding box - int x; - for (x=0; x < len; ++x) { - // cases: - // - // there can be up to two intersections with the pixel. any intersection - // with left or right edges can be handled by splitting into two (or three) - // regions. intersections with top & bottom do not necessitate case-wise logic. - // - // the old way of doing this found the intersections with the left & right edges, - // then used some simple logic to produce up to three segments in sorted order - // from top-to-bottom. however, this had a problem: if an x edge was epsilon - // across the x border, then the corresponding y position might not be distinct - // from the other y segment, and it might ignored as an empty segment. to avoid - // that, we need to explicitly produce segments based on x positions. - - // rename variables to clearly-defined pairs - float y0 = y_top; - float x1 = (float) (x); - float x2 = (float) (x+1); - float x3 = xb; - float y3 = y_bottom; - - // x = e->x + e->dx * (y-y_top) - // (y-y_top) = (x - e->x) / e->dx - // y = (x - e->x) / e->dx + y_top - float y1 = (x - x0) / dx + y_top; - float y2 = (x+1 - x0) / dx + y_top; - - if (x0 < x1 && x3 > x2) { // three segments descending down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else if (x3 < x1 && x0 > x2) { // three segments descending down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); - stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); - } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); - stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else { // one segment - stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); - } - } - } - } - e = e->next; - } -} - -// directly AA rasterize edges w/o supersampling -static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) -{ - stbtt__hheap hh = { 0, 0, 0 }; - stbtt__active_edge *active = NULL; - int y,j=0, i; - float scanline_data[129], *scanline, *scanline2; - - STBTT__NOTUSED(vsubsample); - - if (result->w > 64) - scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); - else - scanline = scanline_data; - - scanline2 = scanline + result->w; - - y = off_y; - e[n].y0 = (float) (off_y + result->h) + 1; - - while (j < result->h) { - // find center of pixel for this scanline - float scan_y_top = y + 0.0f; - float scan_y_bottom = y + 1.0f; - stbtt__active_edge **step = &active; - - STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); - STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); - - // update all active edges; - // remove all active edges that terminate before the top of this scanline - while (*step) { - stbtt__active_edge * z = *step; - if (z->ey <= scan_y_top) { - *step = z->next; // delete from list - STBTT_assert(z->direction); - z->direction = 0; - stbtt__hheap_free(&hh, z); - } else { - step = &((*step)->next); // advance through list - } - } - - // insert all edges that start before the bottom of this scanline - while (e->y0 <= scan_y_bottom) { - if (e->y0 != e->y1) { - stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); - if (z != NULL) { - if (j == 0 && off_y != 0) { - if (z->ey < scan_y_top) { - // this can happen due to subpixel positioning and some kind of fp rounding error i think - z->ey = scan_y_top; - } - } - STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds - // insert at front - z->next = active; - active = z; - } - } - ++e; - } - - // now process all active edges - if (active) - stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); - - { - float sum = 0; - for (i=0; i < result->w; ++i) { - float k; - int m; - sum += scanline2[i]; - k = scanline[i] + sum; - k = (float) STBTT_fabs(k)*255 + 0.5f; - m = (int) k; - if (m > 255) m = 255; - result->pixels[j*result->stride + i] = (unsigned char) m; - } - } - // advance all the edges - step = &active; - while (*step) { - stbtt__active_edge *z = *step; - z->fx += z->fdx; // advance to position for current scanline - step = &((*step)->next); // advance through list - } - - ++y; - ++j; - } - - stbtt__hheap_cleanup(&hh, userdata); - - if (scanline != scanline_data) - STBTT_free(scanline, userdata); -} -#else -#error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif - -#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) - -static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) -{ - int i,j; - for (i=1; i < n; ++i) { - stbtt__edge t = p[i], *a = &t; - j = i; - while (j > 0) { - stbtt__edge *b = &p[j-1]; - int c = STBTT__COMPARE(a,b); - if (!c) break; - p[j] = p[j-1]; - --j; - } - if (i != j) - p[j] = t; - } -} - -static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) -{ - /* threshold for transitioning to insertion sort */ - while (n > 12) { - stbtt__edge t; - int c01,c12,c,m,i,j; - - /* compute median of three */ - m = n >> 1; - c01 = STBTT__COMPARE(&p[0],&p[m]); - c12 = STBTT__COMPARE(&p[m],&p[n-1]); - /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ - if (c01 != c12) { - /* otherwise, we'll need to swap something else to middle */ - int z; - c = STBTT__COMPARE(&p[0],&p[n-1]); - /* 0>mid && midn => n; 0 0 */ - /* 0n: 0>n => 0; 0 n */ - z = (c == c12) ? 0 : n-1; - t = p[z]; - p[z] = p[m]; - p[m] = t; - } - /* now p[m] is the median-of-three */ - /* swap it to the beginning so it won't move around */ - t = p[0]; - p[0] = p[m]; - p[m] = t; - - /* partition loop */ - i=1; - j=n-1; - for(;;) { - /* handling of equality is crucial here */ - /* for sentinels & efficiency with duplicates */ - for (;;++i) { - if (!STBTT__COMPARE(&p[i], &p[0])) break; - } - for (;;--j) { - if (!STBTT__COMPARE(&p[0], &p[j])) break; - } - /* make sure we haven't crossed */ - if (i >= j) break; - t = p[i]; - p[i] = p[j]; - p[j] = t; - - ++i; - --j; - } - /* recurse on smaller side, iterate on larger */ - if (j < (n-i)) { - stbtt__sort_edges_quicksort(p,j); - p = p+i; - n = n-i; - } else { - stbtt__sort_edges_quicksort(p+i, n-i); - n = j; - } - } -} - -static void stbtt__sort_edges(stbtt__edge *p, int n) -{ - stbtt__sort_edges_quicksort(p, n); - stbtt__sort_edges_ins_sort(p, n); -} - -typedef struct -{ - float x,y; -} stbtt__point; - -static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) -{ - float y_scale_inv = invert ? -scale_y : scale_y; - stbtt__edge *e; - int n,i,j,k,m; -#if STBTT_RASTERIZER_VERSION == 1 - int vsubsample = result->h < 8 ? 15 : 5; -#elif STBTT_RASTERIZER_VERSION == 2 - int vsubsample = 1; -#else - #error "Unrecognized value of STBTT_RASTERIZER_VERSION" -#endif - // vsubsample should divide 255 evenly; otherwise we won't reach full opacity - - // now we have to blow out the windings into explicit edge lists - n = 0; - for (i=0; i < windings; ++i) - n += wcount[i]; - - e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel - if (e == 0) return; - n = 0; - - m=0; - for (i=0; i < windings; ++i) { - stbtt__point *p = pts + m; - m += wcount[i]; - j = wcount[i]-1; - for (k=0; k < wcount[i]; j=k++) { - int a=k,b=j; - // skip the edge if horizontal - if (p[j].y == p[k].y) - continue; - // add edge from j to k to the list - e[n].invert = 0; - if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { - e[n].invert = 1; - a=j,b=k; - } - e[n].x0 = p[a].x * scale_x + shift_x; - e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; - e[n].x1 = p[b].x * scale_x + shift_x; - e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; - ++n; - } - } - - // now sort the edges by their highest point (should snap to integer, and then by x) - //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); - stbtt__sort_edges(e, n); - - // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule - stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); - - STBTT_free(e, userdata); -} - -static void stbtt__add_point(stbtt__point *points, int n, float x, float y) -{ - if (!points) return; // during first pass, it's unallocated - points[n].x = x; - points[n].y = y; -} - -// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching -static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) -{ - // midpoint - float mx = (x0 + 2*x1 + x2)/4; - float my = (y0 + 2*y1 + y2)/4; - // versus directly drawn line - float dx = (x0+x2)/2 - mx; - float dy = (y0+y2)/2 - my; - if (n > 16) // 65536 segments on one curve better be enough! - return 1; - if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA - stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); - stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); - } else { - stbtt__add_point(points, *num_points,x2,y2); - *num_points = *num_points+1; - } - return 1; -} - -static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) -{ - // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough - float dx0 = x1-x0; - float dy0 = y1-y0; - float dx1 = x2-x1; - float dy1 = y2-y1; - float dx2 = x3-x2; - float dy2 = y3-y2; - float dx = x3-x0; - float dy = y3-y0; - float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); - float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); - float flatness_squared = longlen*longlen-shortlen*shortlen; - - if (n > 16) // 65536 segments on one curve better be enough! - return; - - if (flatness_squared > objspace_flatness_squared) { - float x01 = (x0+x1)/2; - float y01 = (y0+y1)/2; - float x12 = (x1+x2)/2; - float y12 = (y1+y2)/2; - float x23 = (x2+x3)/2; - float y23 = (y2+y3)/2; - - float xa = (x01+x12)/2; - float ya = (y01+y12)/2; - float xb = (x12+x23)/2; - float yb = (y12+y23)/2; - - float mx = (xa+xb)/2; - float my = (ya+yb)/2; - - stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); - stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); - } else { - stbtt__add_point(points, *num_points,x3,y3); - *num_points = *num_points+1; - } -} - -// returns number of contours -static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) -{ - stbtt__point *points=0; - int num_points=0; - - float objspace_flatness_squared = objspace_flatness * objspace_flatness; - int i,n=0,start=0, pass; - - // count how many "moves" there are to get the contour count - for (i=0; i < num_verts; ++i) - if (vertices[i].type == STBTT_vmove) - ++n; - - *num_contours = n; - if (n == 0) return 0; - - *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); - - if (*contour_lengths == 0) { - *num_contours = 0; - return 0; - } - - // make two passes through the points so we don't need to realloc - for (pass=0; pass < 2; ++pass) { - float x=0,y=0; - if (pass == 1) { - points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); - if (points == NULL) goto error; - } - num_points = 0; - n= -1; - for (i=0; i < num_verts; ++i) { - switch (vertices[i].type) { - case STBTT_vmove: - // start the next contour - if (n >= 0) - (*contour_lengths)[n] = num_points - start; - ++n; - start = num_points; - - x = vertices[i].x, y = vertices[i].y; - stbtt__add_point(points, num_points++, x,y); - break; - case STBTT_vline: - x = vertices[i].x, y = vertices[i].y; - stbtt__add_point(points, num_points++, x, y); - break; - case STBTT_vcurve: - stbtt__tesselate_curve(points, &num_points, x,y, - vertices[i].cx, vertices[i].cy, - vertices[i].x, vertices[i].y, - objspace_flatness_squared, 0); - x = vertices[i].x, y = vertices[i].y; - break; - case STBTT_vcubic: - stbtt__tesselate_cubic(points, &num_points, x,y, - vertices[i].cx, vertices[i].cy, - vertices[i].cx1, vertices[i].cy1, - vertices[i].x, vertices[i].y, - objspace_flatness_squared, 0); - x = vertices[i].x, y = vertices[i].y; - break; - } - } - (*contour_lengths)[n] = num_points - start; - } - - return points; -error: - STBTT_free(points, userdata); - STBTT_free(*contour_lengths, userdata); - *contour_lengths = 0; - *num_contours = 0; - return NULL; -} - -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) -{ - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count = 0; - int *winding_lengths = NULL; - stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); - if (windings) { - stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); - STBTT_free(winding_lengths, userdata); - STBTT_free(windings, userdata); - } -} - -STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) -{ - STBTT_free(bitmap, userdata); -} - -STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) -{ - int ix0,iy0,ix1,iy1; - stbtt__bitmap gbm; - stbtt_vertex *vertices; - int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - - if (scale_x == 0) scale_x = scale_y; - if (scale_y == 0) { - if (scale_x == 0) { - STBTT_free(vertices, info->userdata); - return NULL; - } - scale_y = scale_x; - } - - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); - - // now we get the size - gbm.w = (ix1 - ix0); - gbm.h = (iy1 - iy0); - gbm.pixels = NULL; // in case we error - - if (width ) *width = gbm.w; - if (height) *height = gbm.h; - if (xoff ) *xoff = ix0; - if (yoff ) *yoff = iy0; - - if (gbm.w && gbm.h) { - gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); - if (gbm.pixels) { - gbm.stride = gbm.w; - - stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); - } - } - STBTT_free(vertices, info->userdata); - return gbm.pixels; -} - -STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); -} - -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) -{ - int ix0,iy0; - stbtt_vertex *vertices; - int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - stbtt__bitmap gbm; - - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); - gbm.pixels = output; - gbm.w = out_w; - gbm.h = out_h; - gbm.stride = out_stride; - - if (gbm.w && gbm.h) - stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); - - STBTT_free(vertices, info->userdata); -} - -STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) -{ - stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); -} - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); -} - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) -{ - stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); -} - -STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) -{ - stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); -} - -STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); -} - -STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) -{ - stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); -} - -////////////////////////////////////////////////////////////////////////////// -// -// bitmap baking -// -// This is SUPER-CRAPPY packing to keep source code small - -static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) - float pixel_height, // height of font in pixels - unsigned char *pixels, int pw, int ph, // bitmap to be filled in - int first_char, int num_chars, // characters to bake - stbtt_bakedchar *chardata) -{ - float scale; - int x,y,bottom_y, i; - stbtt_fontinfo f; - f.userdata = NULL; - if (!stbtt_InitFont(&f, data, offset)) - return -1; - STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels - x=y=1; - bottom_y = 1; - - scale = stbtt_ScaleForPixelHeight(&f, pixel_height); - - for (i=0; i < num_chars; ++i) { - int advance, lsb, x0,y0,x1,y1,gw,gh; - int g = stbtt_FindGlyphIndex(&f, first_char + i); - stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); - stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); - gw = x1-x0; - gh = y1-y0; - if (x + gw + 1 >= pw) - y = bottom_y, x = 1; // advance to next row - if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row - return -i; - STBTT_assert(x+gw < pw); - STBTT_assert(y+gh < ph); - stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); - chardata[i].x0 = (stbtt_int16) x; - chardata[i].y0 = (stbtt_int16) y; - chardata[i].x1 = (stbtt_int16) (x + gw); - chardata[i].y1 = (stbtt_int16) (y + gh); - chardata[i].xadvance = scale * advance; - chardata[i].xoff = (float) x0; - chardata[i].yoff = (float) y0; - x = x + gw + 1; - if (y+gh+1 > bottom_y) - bottom_y = y+gh+1; - } - return bottom_y; -} - -STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) -{ - float d3d_bias = opengl_fillrule ? 0 : -0.5f; - float ipw = 1.0f / pw, iph = 1.0f / ph; - const stbtt_bakedchar *b = chardata + char_index; - int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); - int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); - - q->x0 = round_x + d3d_bias; - q->y0 = round_y + d3d_bias; - q->x1 = round_x + b->x1 - b->x0 + d3d_bias; - q->y1 = round_y + b->y1 - b->y0 + d3d_bias; - - q->s0 = b->x0 * ipw; - q->t0 = b->y0 * iph; - q->s1 = b->x1 * ipw; - q->t1 = b->y1 * iph; - - *xpos += b->xadvance; -} - -////////////////////////////////////////////////////////////////////////////// -// -// rectangle packing replacement routines if you don't have stb_rect_pack.h -// - -#ifndef STB_RECT_PACK_VERSION - -typedef int stbrp_coord; - -//////////////////////////////////////////////////////////////////////////////////// -// // -// // -// COMPILER WARNING ?!?!? // -// // -// // -// if you get a compile warning due to these symbols being defined more than // -// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // -// // -//////////////////////////////////////////////////////////////////////////////////// - -typedef struct -{ - int width,height; - int x,y,bottom_y; -} stbrp_context; - -typedef struct -{ - unsigned char x; -} stbrp_node; - -struct stbrp_rect -{ - stbrp_coord x,y; - int id,w,h,was_packed; -}; - -static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) -{ - con->width = pw; - con->height = ph; - con->x = 0; - con->y = 0; - con->bottom_y = 0; - STBTT__NOTUSED(nodes); - STBTT__NOTUSED(num_nodes); -} - -static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) -{ - int i; - for (i=0; i < num_rects; ++i) { - if (con->x + rects[i].w > con->width) { - con->x = 0; - con->y = con->bottom_y; - } - if (con->y + rects[i].h > con->height) - break; - rects[i].x = con->x; - rects[i].y = con->y; - rects[i].was_packed = 1; - con->x += rects[i].w; - if (con->y + rects[i].h > con->bottom_y) - con->bottom_y = con->y + rects[i].h; - } - for ( ; i < num_rects; ++i) - rects[i].was_packed = 0; -} -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// bitmap baking -// -// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If -// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. - -STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) -{ - stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); - int num_nodes = pw - padding; - stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); - - if (context == NULL || nodes == NULL) { - if (context != NULL) STBTT_free(context, alloc_context); - if (nodes != NULL) STBTT_free(nodes , alloc_context); - return 0; - } - - spc->user_allocator_context = alloc_context; - spc->width = pw; - spc->height = ph; - spc->pixels = pixels; - spc->pack_info = context; - spc->nodes = nodes; - spc->padding = padding; - spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; - spc->h_oversample = 1; - spc->v_oversample = 1; - spc->skip_missing = 0; - - stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); - - if (pixels) - STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels - - return 1; -} - -STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) -{ - STBTT_free(spc->nodes , spc->user_allocator_context); - STBTT_free(spc->pack_info, spc->user_allocator_context); -} - -STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) -{ - STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); - STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); - if (h_oversample <= STBTT_MAX_OVERSAMPLE) - spc->h_oversample = h_oversample; - if (v_oversample <= STBTT_MAX_OVERSAMPLE) - spc->v_oversample = v_oversample; -} - -STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) -{ - spc->skip_missing = skip; -} - -#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) - -static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) -{ - unsigned char buffer[STBTT_MAX_OVERSAMPLE]; - int safe_w = w - kernel_width; - int j; - STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze - for (j=0; j < h; ++j) { - int i; - unsigned int total; - STBTT_memset(buffer, 0, kernel_width); - - total = 0; - - // make kernel_width a constant in common cases so compiler can optimize out the divide - switch (kernel_width) { - case 2: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 2); - } - break; - case 3: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 3); - } - break; - case 4: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 4); - } - break; - case 5: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 5); - } - break; - default: - for (i=0; i <= safe_w; ++i) { - total += pixels[i] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / kernel_width); - } - break; - } - - for (; i < w; ++i) { - STBTT_assert(pixels[i] == 0); - total -= buffer[i & STBTT__OVER_MASK]; - pixels[i] = (unsigned char) (total / kernel_width); - } - - pixels += stride_in_bytes; - } -} - -static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) -{ - unsigned char buffer[STBTT_MAX_OVERSAMPLE]; - int safe_h = h - kernel_width; - int j; - STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze - for (j=0; j < w; ++j) { - int i; - unsigned int total; - STBTT_memset(buffer, 0, kernel_width); - - total = 0; - - // make kernel_width a constant in common cases so compiler can optimize out the divide - switch (kernel_width) { - case 2: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 2); - } - break; - case 3: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 3); - } - break; - case 4: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 4); - } - break; - case 5: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 5); - } - break; - default: - for (i=0; i <= safe_h; ++i) { - total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; - buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); - } - break; - } - - for (; i < h; ++i) { - STBTT_assert(pixels[i*stride_in_bytes] == 0); - total -= buffer[i & STBTT__OVER_MASK]; - pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); - } - - pixels += 1; - } -} - -static float stbtt__oversample_shift(int oversample) -{ - if (!oversample) - return 0.0f; - - // The prefilter is a box filter of width "oversample", - // which shifts phase by (oversample - 1)/2 pixels in - // oversampled space. We want to shift in the opposite - // direction to counter this. - return (float)-(oversample - 1) / (2.0f * (float)oversample); -} - -// rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) -{ - int i,j,k; - int missing_glyph_added = 0; - - k=0; - for (i=0; i < num_ranges; ++i) { - float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); - ranges[i].h_oversample = (unsigned char) spc->h_oversample; - ranges[i].v_oversample = (unsigned char) spc->v_oversample; - for (j=0; j < ranges[i].num_chars; ++j) { - int x0,y0,x1,y1; - int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; - int glyph = stbtt_FindGlyphIndex(info, codepoint); - if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { - rects[k].w = rects[k].h = 0; - } else { - stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - &x0,&y0,&x1,&y1); - rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); - rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); - if (glyph == 0) - missing_glyph_added = 1; - } - ++k; - } - } - - return k; -} - -STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) -{ - stbtt_MakeGlyphBitmapSubpixel(info, - output, - out_w - (prefilter_x - 1), - out_h - (prefilter_y - 1), - out_stride, - scale_x, - scale_y, - shift_x, - shift_y, - glyph); - - if (prefilter_x > 1) - stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); - - if (prefilter_y > 1) - stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); - - *sub_x = stbtt__oversample_shift(prefilter_x); - *sub_y = stbtt__oversample_shift(prefilter_y); -} - -// rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) -{ - int i,j,k, missing_glyph = -1, return_value = 1; - - // save current values - int old_h_over = spc->h_oversample; - int old_v_over = spc->v_oversample; - - k = 0; - for (i=0; i < num_ranges; ++i) { - float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); - float recip_h,recip_v,sub_x,sub_y; - spc->h_oversample = ranges[i].h_oversample; - spc->v_oversample = ranges[i].v_oversample; - recip_h = 1.0f / spc->h_oversample; - recip_v = 1.0f / spc->v_oversample; - sub_x = stbtt__oversample_shift(spc->h_oversample); - sub_y = stbtt__oversample_shift(spc->v_oversample); - for (j=0; j < ranges[i].num_chars; ++j) { - stbrp_rect *r = &rects[k]; - if (r->was_packed && r->w != 0 && r->h != 0) { - stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; - int advance, lsb, x0,y0,x1,y1; - int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; - int glyph = stbtt_FindGlyphIndex(info, codepoint); - stbrp_coord pad = (stbrp_coord) spc->padding; - - // pad on left and top - r->x += pad; - r->y += pad; - r->w -= pad; - r->h -= pad; - stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); - stbtt_GetGlyphBitmapBox(info, glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - &x0,&y0,&x1,&y1); - stbtt_MakeGlyphBitmapSubpixel(info, - spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w - spc->h_oversample+1, - r->h - spc->v_oversample+1, - spc->stride_in_bytes, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - glyph); - - if (spc->h_oversample > 1) - stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, - spc->h_oversample); - - if (spc->v_oversample > 1) - stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, - spc->v_oversample); - - bc->x0 = (stbtt_int16) r->x; - bc->y0 = (stbtt_int16) r->y; - bc->x1 = (stbtt_int16) (r->x + r->w); - bc->y1 = (stbtt_int16) (r->y + r->h); - bc->xadvance = scale * advance; - bc->xoff = (float) x0 * recip_h + sub_x; - bc->yoff = (float) y0 * recip_v + sub_y; - bc->xoff2 = (x0 + r->w) * recip_h + sub_x; - bc->yoff2 = (y0 + r->h) * recip_v + sub_y; - - if (glyph == 0) - missing_glyph = j; - } else if (spc->skip_missing) { - return_value = 0; - } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { - ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; - } else { - return_value = 0; // if any fail, report failure - } - - ++k; - } - } - - // restore original values - spc->h_oversample = old_h_over; - spc->v_oversample = old_v_over; - - return return_value; -} - -STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) -{ - stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); -} - -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) -{ - stbtt_fontinfo info; - int i,j,n, return_value = 1; - //stbrp_context *context = (stbrp_context *) spc->pack_info; - stbrp_rect *rects; - - // flag all characters as NOT packed - for (i=0; i < num_ranges; ++i) - for (j=0; j < ranges[i].num_chars; ++j) - ranges[i].chardata_for_range[j].x0 = - ranges[i].chardata_for_range[j].y0 = - ranges[i].chardata_for_range[j].x1 = - ranges[i].chardata_for_range[j].y1 = 0; - - n = 0; - for (i=0; i < num_ranges; ++i) - n += ranges[i].num_chars; - - rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); - if (rects == NULL) - return 0; - - info.userdata = spc->user_allocator_context; - stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); - - n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); - - stbtt_PackFontRangesPackRects(spc, rects, n); - - return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); - - STBTT_free(rects, spc->user_allocator_context); - return return_value; -} - -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, - int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) -{ - stbtt_pack_range range; - range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; - range.array_of_unicode_codepoints = NULL; - range.num_chars = num_chars_in_range; - range.chardata_for_range = chardata_for_range; - range.font_size = font_size; - return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); -} - -STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) -{ - int i_ascent, i_descent, i_lineGap; - float scale; - stbtt_fontinfo info; - stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); - scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); - stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); - *ascent = (float) i_ascent * scale; - *descent = (float) i_descent * scale; - *lineGap = (float) i_lineGap * scale; -} - -STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) -{ - float ipw = 1.0f / pw, iph = 1.0f / ph; - const stbtt_packedchar *b = chardata + char_index; - - if (align_to_integer) { - float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); - float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); - q->x0 = x; - q->y0 = y; - q->x1 = x + b->xoff2 - b->xoff; - q->y1 = y + b->yoff2 - b->yoff; - } else { - q->x0 = *xpos + b->xoff; - q->y0 = *ypos + b->yoff; - q->x1 = *xpos + b->xoff2; - q->y1 = *ypos + b->yoff2; - } - - q->s0 = b->x0 * ipw; - q->t0 = b->y0 * iph; - q->s1 = b->x1 * ipw; - q->t1 = b->y1 * iph; - - *xpos += b->xadvance; -} - -////////////////////////////////////////////////////////////////////////////// -// -// sdf computation -// - -#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) -#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) - -static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) -{ - float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; - float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; - float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; - float roperp = orig[1]*ray[0] - orig[0]*ray[1]; - - float a = q0perp - 2*q1perp + q2perp; - float b = q1perp - q0perp; - float c = q0perp - roperp; - - float s0 = 0., s1 = 0.; - int num_s = 0; - - if (a != 0.0) { - float discr = b*b - a*c; - if (discr > 0.0) { - float rcpna = -1 / a; - float d = (float) STBTT_sqrt(discr); - s0 = (b+d) * rcpna; - s1 = (b-d) * rcpna; - if (s0 >= 0.0 && s0 <= 1.0) - num_s = 1; - if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { - if (num_s == 0) s0 = s1; - ++num_s; - } - } - } else { - // 2*b*s + c = 0 - // s = -c / (2*b) - s0 = c / (-2 * b); - if (s0 >= 0.0 && s0 <= 1.0) - num_s = 1; - } - - if (num_s == 0) - return 0; - else { - float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); - float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; - - float q0d = q0[0]*rayn_x + q0[1]*rayn_y; - float q1d = q1[0]*rayn_x + q1[1]*rayn_y; - float q2d = q2[0]*rayn_x + q2[1]*rayn_y; - float rod = orig[0]*rayn_x + orig[1]*rayn_y; - - float q10d = q1d - q0d; - float q20d = q2d - q0d; - float q0rd = q0d - rod; - - hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; - hits[0][1] = a*s0+b; - - if (num_s > 1) { - hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; - hits[1][1] = a*s1+b; - return 2; - } else { - return 1; - } - } -} - -static int equal(float *a, float *b) -{ - return (a[0] == b[0] && a[1] == b[1]); -} - -static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) -{ - int i; - float orig[2], ray[2] = { 1, 0 }; - float y_frac; - int winding = 0; - - // make sure y never passes through a vertex of the shape - y_frac = (float) STBTT_fmod(y, 1.0f); - if (y_frac < 0.01f) - y += 0.01f; - else if (y_frac > 0.99f) - y -= 0.01f; - - orig[0] = x; - orig[1] = y; - - // test a ray from (-infinity,y) to (x,y) - for (i=0; i < nverts; ++i) { - if (verts[i].type == STBTT_vline) { - int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; - int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; - if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { - float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; - if (x_inter < x) - winding += (y0 < y1) ? 1 : -1; - } - } - if (verts[i].type == STBTT_vcurve) { - int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; - int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; - int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; - int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); - int by = STBTT_max(y0,STBTT_max(y1,y2)); - if (y > ay && y < by && x > ax) { - float q0[2],q1[2],q2[2]; - float hits[2][2]; - q0[0] = (float)x0; - q0[1] = (float)y0; - q1[0] = (float)x1; - q1[1] = (float)y1; - q2[0] = (float)x2; - q2[1] = (float)y2; - if (equal(q0,q1) || equal(q1,q2)) { - x0 = (int)verts[i-1].x; - y0 = (int)verts[i-1].y; - x1 = (int)verts[i ].x; - y1 = (int)verts[i ].y; - if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { - float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; - if (x_inter < x) - winding += (y0 < y1) ? 1 : -1; - } - } else { - int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); - if (num_hits >= 1) - if (hits[0][0] < 0) - winding += (hits[0][1] < 0 ? -1 : 1); - if (num_hits >= 2) - if (hits[1][0] < 0) - winding += (hits[1][1] < 0 ? -1 : 1); - } - } - } - } - return winding; -} - -static float stbtt__cuberoot( float x ) -{ - if (x<0) - return -(float) STBTT_pow(-x,1.0f/3.0f); - else - return (float) STBTT_pow( x,1.0f/3.0f); -} - -// x^3 + a*x^2 + b*x + c = 0 -static int stbtt__solve_cubic(float a, float b, float c, float* r) -{ - float s = -a / 3; - float p = b - a*a / 3; - float q = a * (2*a*a - 9*b) / 27 + c; - float p3 = p*p*p; - float d = q*q + 4*p3 / 27; - if (d >= 0) { - float z = (float) STBTT_sqrt(d); - float u = (-q + z) / 2; - float v = (-q - z) / 2; - u = stbtt__cuberoot(u); - v = stbtt__cuberoot(v); - r[0] = s + u + v; - return 1; - } else { - float u = (float) STBTT_sqrt(-p/3); - float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative - float m = (float) STBTT_cos(v); - float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; - r[0] = s + u * 2 * m; - r[1] = s - u * (m + n); - r[2] = s - u * (m - n); - - //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? - //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); - //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); - return 3; - } -} - -STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) -{ - float scale_x = scale, scale_y = scale; - int ix0,iy0,ix1,iy1; - int w,h; - unsigned char *data; - - if (scale == 0) return NULL; - - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); - - // if empty, return NULL - if (ix0 == ix1 || iy0 == iy1) - return NULL; - - ix0 -= padding; - iy0 -= padding; - ix1 += padding; - iy1 += padding; - - w = (ix1 - ix0); - h = (iy1 - iy0); - - if (width ) *width = w; - if (height) *height = h; - if (xoff ) *xoff = ix0; - if (yoff ) *yoff = iy0; - - // invert for y-downwards bitmaps - scale_y = -scale_y; - - { - int x,y,i,j; - float *precompute; - stbtt_vertex *verts; - int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); - data = (unsigned char *) STBTT_malloc(w * h, info->userdata); - precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); - - for (i=0,j=num_verts-1; i < num_verts; j=i++) { - if (verts[i].type == STBTT_vline) { - float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; - float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; - float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); - precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; - } else if (verts[i].type == STBTT_vcurve) { - float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; - float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; - float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; - float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; - float len2 = bx*bx + by*by; - if (len2 != 0.0f) - precompute[i] = 1.0f / (bx*bx + by*by); - else - precompute[i] = 0.0f; - } else - precompute[i] = 0.0f; - } - - for (y=iy0; y < iy1; ++y) { - for (x=ix0; x < ix1; ++x) { - float val; - float min_dist = 999999.0f; - float sx = (float) x + 0.5f; - float sy = (float) y + 0.5f; - float x_gspace = (sx / scale_x); - float y_gspace = (sy / scale_y); - - int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path - - for (i=0; i < num_verts; ++i) { - float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; - - if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { - float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; - - float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); - if (dist2 < min_dist*min_dist) - min_dist = (float) STBTT_sqrt(dist2); - - // coarse culling against bbox - //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && - // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) - dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; - STBTT_assert(i != 0); - if (dist < min_dist) { - // check position along line - // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) - // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) - float dx = x1-x0, dy = y1-y0; - float px = x0-sx, py = y0-sy; - // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy - // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve - float t = -(px*dx + py*dy) / (dx*dx + dy*dy); - if (t >= 0.0f && t <= 1.0f) - min_dist = dist; - } - } else if (verts[i].type == STBTT_vcurve) { - float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; - float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; - float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); - float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); - float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); - float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); - // coarse culling against bbox to avoid computing cubic unnecessarily - if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { - int num=0; - float ax = x1-x0, ay = y1-y0; - float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; - float mx = x0 - sx, my = y0 - sy; - float res[3] = {0.f,0.f,0.f}; - float px,py,t,it,dist2; - float a_inv = precompute[i]; - if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula - float a = 3*(ax*bx + ay*by); - float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); - float c = mx*ax+my*ay; - if (a == 0.0) { // if a is 0, it's linear - if (b != 0.0) { - res[num++] = -c/b; - } - } else { - float discriminant = b*b - 4*a*c; - if (discriminant < 0) - num = 0; - else { - float root = (float) STBTT_sqrt(discriminant); - res[0] = (-b - root)/(2*a); - res[1] = (-b + root)/(2*a); - num = 2; // don't bother distinguishing 1-solution case, as code below will still work - } - } - } else { - float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point - float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; - float d = (mx*ax+my*ay) * a_inv; - num = stbtt__solve_cubic(b, c, d, res); - } - dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); - if (dist2 < min_dist*min_dist) - min_dist = (float) STBTT_sqrt(dist2); - - if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { - t = res[0], it = 1.0f - t; - px = it*it*x0 + 2*t*it*x1 + t*t*x2; - py = it*it*y0 + 2*t*it*y1 + t*t*y2; - dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); - if (dist2 < min_dist * min_dist) - min_dist = (float) STBTT_sqrt(dist2); - } - if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { - t = res[1], it = 1.0f - t; - px = it*it*x0 + 2*t*it*x1 + t*t*x2; - py = it*it*y0 + 2*t*it*y1 + t*t*y2; - dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); - if (dist2 < min_dist * min_dist) - min_dist = (float) STBTT_sqrt(dist2); - } - if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { - t = res[2], it = 1.0f - t; - px = it*it*x0 + 2*t*it*x1 + t*t*x2; - py = it*it*y0 + 2*t*it*y1 + t*t*y2; - dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); - if (dist2 < min_dist * min_dist) - min_dist = (float) STBTT_sqrt(dist2); - } - } - } - } - if (winding == 0) - min_dist = -min_dist; // if outside the shape, value is negative - val = onedge_value + pixel_dist_scale * min_dist; - if (val < 0) - val = 0; - else if (val > 255) - val = 255; - data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; - } - } - STBTT_free(precompute, info->userdata); - STBTT_free(verts, info->userdata); - } - return data; -} - -STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); -} - -STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) -{ - STBTT_free(bitmap, userdata); -} - -////////////////////////////////////////////////////////////////////////////// -// -// font name matching -- recommended not to use this -// - -// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string -static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) -{ - stbtt_int32 i=0; - - // convert utf16 to utf8 and compare the results while converting - while (len2) { - stbtt_uint16 ch = s2[0]*256 + s2[1]; - if (ch < 0x80) { - if (i >= len1) return -1; - if (s1[i++] != ch) return -1; - } else if (ch < 0x800) { - if (i+1 >= len1) return -1; - if (s1[i++] != 0xc0 + (ch >> 6)) return -1; - if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; - } else if (ch >= 0xd800 && ch < 0xdc00) { - stbtt_uint32 c; - stbtt_uint16 ch2 = s2[2]*256 + s2[3]; - if (i+3 >= len1) return -1; - c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; - if (s1[i++] != 0xf0 + (c >> 18)) return -1; - if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; - s2 += 2; // plus another 2 below - len2 -= 2; - } else if (ch >= 0xdc00 && ch < 0xe000) { - return -1; - } else { - if (i+2 >= len1) return -1; - if (s1[i++] != 0xe0 + (ch >> 12)) return -1; - if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; - if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; - } - s2 += 2; - len2 -= 2; - } - return i; -} - -static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) -{ - return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); -} - -// returns results in whatever encoding you request... but note that 2-byte encodings -// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare -STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) -{ - stbtt_int32 i,count,stringOffset; - stbtt_uint8 *fc = font->data; - stbtt_uint32 offset = font->fontstart; - stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); - if (!nm) return NULL; - - count = ttUSHORT(fc+nm+2); - stringOffset = nm + ttUSHORT(fc+nm+4); - for (i=0; i < count; ++i) { - stbtt_uint32 loc = nm + 6 + 12 * i; - if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) - && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { - *length = ttUSHORT(fc+loc+8); - return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); - } - } - return NULL; -} - -static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) -{ - stbtt_int32 i; - stbtt_int32 count = ttUSHORT(fc+nm+2); - stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); - - for (i=0; i < count; ++i) { - stbtt_uint32 loc = nm + 6 + 12 * i; - stbtt_int32 id = ttUSHORT(fc+loc+6); - if (id == target_id) { - // find the encoding - stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); - - // is this a Unicode encoding? - if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { - stbtt_int32 slen = ttUSHORT(fc+loc+8); - stbtt_int32 off = ttUSHORT(fc+loc+10); - - // check if there's a prefix match - stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); - if (matchlen >= 0) { - // check for target_id+1 immediately following, with same encoding & language - if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { - slen = ttUSHORT(fc+loc+12+8); - off = ttUSHORT(fc+loc+12+10); - if (slen == 0) { - if (matchlen == nlen) - return 1; - } else if (matchlen < nlen && name[matchlen] == ' ') { - ++matchlen; - if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) - return 1; - } - } else { - // if nothing immediately following - if (matchlen == nlen) - return 1; - } - } - } - - // @TODO handle other encodings - } - } - return 0; -} - -static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) -{ - stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); - stbtt_uint32 nm,hd; - if (!stbtt__isfont(fc+offset)) return 0; - - // check italics/bold/underline flags in macStyle... - if (flags) { - hd = stbtt__find_table(fc, offset, "head"); - if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; - } - - nm = stbtt__find_table(fc, offset, "name"); - if (!nm) return 0; - - if (flags) { - // if we checked the macStyle flags, then just check the family and ignore the subfamily - if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; - } else { - if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; - if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; - } - - return 0; -} - -static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) -{ - stbtt_int32 i; - for (i=0;;++i) { - stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); - if (off < 0) return off; - if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) - return off; - } -} - -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, - float pixel_height, unsigned char *pixels, int pw, int ph, - int first_char, int num_chars, stbtt_bakedchar *chardata) -{ - return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); -} - -STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) -{ - return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); -} - -STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) -{ - return stbtt_GetNumberOfFonts_internal((unsigned char *) data); -} - -STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) -{ - return stbtt_InitFont_internal(info, (unsigned char *) data, offset); -} - -STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) -{ - return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); -} - -STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) -{ - return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); -} - -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic pop -#endif - -#endif // STB_TRUETYPE_IMPLEMENTATION - - -// FULL VERSION HISTORY -// -// 1.25 (2021-07-11) many fixes -// 1.24 (2020-02-05) fix warning -// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) -// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined -// 1.21 (2019-02-25) fix warning -// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() -// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod -// 1.18 (2018-01-29) add missing function -// 1.17 (2017-07-23) make more arguments const; doc fix -// 1.16 (2017-07-12) SDF support -// 1.15 (2017-03-03) make more arguments const -// 1.14 (2017-01-16) num-fonts-in-TTC function -// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts -// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual -// 1.11 (2016-04-02) fix unused-variable warning -// 1.10 (2016-04-02) allow user-defined fabs() replacement -// fix memory leak if fontsize=0.0 -// fix warning from duplicate typedef -// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges -// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges -// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; -// allow PackFontRanges to pack and render in separate phases; -// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); -// fixed an assert() bug in the new rasterizer -// replace assert() with STBTT_assert() in new rasterizer -// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) -// also more precise AA rasterizer, except if shapes overlap -// remove need for STBTT_sort -// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC -// 1.04 (2015-04-15) typo in example -// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes -// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ -// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match -// non-oversampled; STBTT_POINT_SIZE for packed case only -// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling -// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) -// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID -// 0.8b (2014-07-07) fix a warning -// 0.8 (2014-05-25) fix a few more warnings -// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back -// 0.6c (2012-07-24) improve documentation -// 0.6b (2012-07-20) fix a few more warnings -// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, -// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty -// 0.5 (2011-12-09) bugfixes: -// subpixel glyph renderer computed wrong bounding box -// first vertex of shape can be off-curve (FreeSans) -// 0.4b (2011-12-03) fixed an error in the font baking example -// 0.4 (2011-12-01) kerning, subpixel rendering (tor) -// bugfixes for: -// codepoint-to-glyph conversion using table fmt=12 -// codepoint-to-glyph conversion using table fmt=4 -// stbtt_GetBakedQuad with non-square texture (Zer) -// updated Hello World! sample to use kerning and subpixel -// fixed some warnings -// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) -// userdata, malloc-from-userdata, non-zero fill (stb) -// 0.2 (2009-03-11) Fix unsigned/signed char warnings -// 0.1 (2009-03-09) First public release -// - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/resources/stb_vorbis.c --- a/src/semicongine/resources/stb_vorbis.c Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5584 +0,0 @@ -// Ogg Vorbis audio decoder - v1.22 - public domain -// http://nothings.org/stb_vorbis/ -// -// Original version written by Sean Barrett in 2007. -// -// Originally sponsored by RAD Game Tools. Seeking implementation -// sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker, -// Elias Software, Aras Pranckevicius, and Sean Barrett. -// -// LICENSE -// -// See end of file for license information. -// -// Limitations: -// -// - floor 0 not supported (used in old ogg vorbis files pre-2004) -// - lossless sample-truncation at beginning ignored -// - cannot concatenate multiple vorbis streams -// - sample positions are 32-bit, limiting seekable 192Khz -// files to around 6 hours (Ogg supports 64-bit) -// -// Feature contributors: -// Dougall Johnson (sample-exact seeking) -// -// Bugfix/warning contributors: -// Terje Mathisen Niklas Frykholm Andy Hill -// Casey Muratori John Bolton Gargaj -// Laurent Gomila Marc LeBlanc Ronny Chevalier -// Bernhard Wodo Evan Balster github:alxprd -// Tom Beaumont Ingo Leitgeb Nicolas Guillemot -// Phillip Bennefall Rohit Thiago Goulart -// github:manxorist Saga Musix github:infatum -// Timur Gagiev Maxwell Koo Peter Waller -// github:audinowho Dougall Johnson David Reid -// github:Clownacy Pedro J. Estebanez Remi Verschelde -// AnthoFoxo github:morlat Gabriel Ravier -// -// Partial history: -// 1.22 - 2021-07-11 - various small fixes -// 1.21 - 2021-07-02 - fix bug for files with no comments -// 1.20 - 2020-07-11 - several small fixes -// 1.19 - 2020-02-05 - warnings -// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc. -// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure) -// 1.16 - 2019-03-04 - fix warnings -// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found -// 1.14 - 2018-02-11 - delete bogus dealloca usage -// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully) -// 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files -// 1.11 - 2017-07-23 - fix MinGW compilation -// 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory -// 1.09 - 2016-04-04 - back out 'truncation of last frame' fix from previous version -// 1.08 - 2016-04-02 - warnings; setup memory leaks; truncation of last frame -// 1.07 - 2015-01-16 - fixes for crashes on invalid files; warning fixes; const -// 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson) -// some crash fixes when out of memory or with corrupt files -// fix some inappropriately signed shifts -// 1.05 - 2015-04-19 - don't define __forceinline if it's redundant -// 1.04 - 2014-08-27 - fix missing const-correct case in API -// 1.03 - 2014-08-07 - warning fixes -// 1.02 - 2014-07-09 - declare qsort comparison as explicitly _cdecl in Windows -// 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float (interleaved was correct) -// 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in >2-channel; -// (API change) report sample rate for decode-full-file funcs -// -// See end of file for full version history. - - -////////////////////////////////////////////////////////////////////////////// -// -// HEADER BEGINS HERE -// - -#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H -#define STB_VORBIS_INCLUDE_STB_VORBIS_H - -#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) -#define STB_VORBIS_NO_STDIO 1 -#endif - -#ifndef STB_VORBIS_NO_STDIO -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/////////// THREAD SAFETY - -// Individual stb_vorbis* handles are not thread-safe; you cannot decode from -// them from multiple threads at the same time. However, you can have multiple -// stb_vorbis* handles and decode from them independently in multiple thrads. - - -/////////// MEMORY ALLOCATION - -// normally stb_vorbis uses malloc() to allocate memory at startup, -// and alloca() to allocate temporary memory during a frame on the -// stack. (Memory consumption will depend on the amount of setup -// data in the file and how you set the compile flags for speed -// vs. size. In my test files the maximal-size usage is ~150KB.) -// -// You can modify the wrapper functions in the source (setup_malloc, -// setup_temp_malloc, temp_malloc) to change this behavior, or you -// can use a simpler allocation model: you pass in a buffer from -// which stb_vorbis will allocate _all_ its memory (including the -// temp memory). "open" may fail with a VORBIS_outofmem if you -// do not pass in enough data; there is no way to determine how -// much you do need except to succeed (at which point you can -// query get_info to find the exact amount required. yes I know -// this is lame). -// -// If you pass in a non-NULL buffer of the type below, allocation -// will occur from it as described above. Otherwise just pass NULL -// to use malloc()/alloca() - -typedef struct -{ - char *alloc_buffer; - int alloc_buffer_length_in_bytes; -} stb_vorbis_alloc; - - -/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES - -typedef struct stb_vorbis stb_vorbis; - -typedef struct -{ - unsigned int sample_rate; - int channels; - - unsigned int setup_memory_required; - unsigned int setup_temp_memory_required; - unsigned int temp_memory_required; - - int max_frame_size; -} stb_vorbis_info; - -typedef struct -{ - char *vendor; - - int comment_list_length; - char **comment_list; -} stb_vorbis_comment; - -// get general information about the file -extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f); - -// get ogg comments -extern stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f); - -// get the last error detected (clears it, too) -extern int stb_vorbis_get_error(stb_vorbis *f); - -// close an ogg vorbis file and free all memory in use -extern void stb_vorbis_close(stb_vorbis *f); - -// this function returns the offset (in samples) from the beginning of the -// file that will be returned by the next decode, if it is known, or -1 -// otherwise. after a flush_pushdata() call, this may take a while before -// it becomes valid again. -// NOT WORKING YET after a seek with PULLDATA API -extern int stb_vorbis_get_sample_offset(stb_vorbis *f); - -// returns the current seek point within the file, or offset from the beginning -// of the memory buffer. In pushdata mode it returns 0. -extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f); - -/////////// PUSHDATA API - -#ifndef STB_VORBIS_NO_PUSHDATA_API - -// this API allows you to get blocks of data from any source and hand -// them to stb_vorbis. you have to buffer them; stb_vorbis will tell -// you how much it used, and you have to give it the rest next time; -// and stb_vorbis may not have enough data to work with and you will -// need to give it the same data again PLUS more. Note that the Vorbis -// specification does not bound the size of an individual frame. - -extern stb_vorbis *stb_vorbis_open_pushdata( - const unsigned char * datablock, int datablock_length_in_bytes, - int *datablock_memory_consumed_in_bytes, - int *error, - const stb_vorbis_alloc *alloc_buffer); -// create a vorbis decoder by passing in the initial data block containing -// the ogg&vorbis headers (you don't need to do parse them, just provide -// the first N bytes of the file--you're told if it's not enough, see below) -// on success, returns an stb_vorbis *, does not set error, returns the amount of -// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes; -// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed -// if returns NULL and *error is VORBIS_need_more_data, then the input block was -// incomplete and you need to pass in a larger block from the start of the file - -extern int stb_vorbis_decode_frame_pushdata( - stb_vorbis *f, - const unsigned char *datablock, int datablock_length_in_bytes, - int *channels, // place to write number of float * buffers - float ***output, // place to write float ** array of float * buffers - int *samples // place to write number of output samples - ); -// decode a frame of audio sample data if possible from the passed-in data block -// -// return value: number of bytes we used from datablock -// -// possible cases: -// 0 bytes used, 0 samples output (need more data) -// N bytes used, 0 samples output (resynching the stream, keep going) -// N bytes used, M samples output (one frame of data) -// note that after opening a file, you will ALWAYS get one N-bytes,0-sample -// frame, because Vorbis always "discards" the first frame. -// -// Note that on resynch, stb_vorbis will rarely consume all of the buffer, -// instead only datablock_length_in_bytes-3 or less. This is because it wants -// to avoid missing parts of a page header if they cross a datablock boundary, -// without writing state-machiney code to record a partial detection. -// -// The number of channels returned are stored in *channels (which can be -// NULL--it is always the same as the number of channels reported by -// get_info). *output will contain an array of float* buffers, one per -// channel. In other words, (*output)[0][0] contains the first sample from -// the first channel, and (*output)[1][0] contains the first sample from -// the second channel. -// -// *output points into stb_vorbis's internal output buffer storage; these -// buffers are owned by stb_vorbis and application code should not free -// them or modify their contents. They are transient and will be overwritten -// once you ask for more data to get decoded, so be sure to grab any data -// you need before then. - -extern void stb_vorbis_flush_pushdata(stb_vorbis *f); -// inform stb_vorbis that your next datablock will not be contiguous with -// previous ones (e.g. you've seeked in the data); future attempts to decode -// frames will cause stb_vorbis to resynchronize (as noted above), and -// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it -// will begin decoding the _next_ frame. -// -// if you want to seek using pushdata, you need to seek in your file, then -// call stb_vorbis_flush_pushdata(), then start calling decoding, then once -// decoding is returning you data, call stb_vorbis_get_sample_offset, and -// if you don't like the result, seek your file again and repeat. -#endif - - -////////// PULLING INPUT API - -#ifndef STB_VORBIS_NO_PULLDATA_API -// This API assumes stb_vorbis is allowed to pull data from a source-- -// either a block of memory containing the _entire_ vorbis stream, or a -// FILE * that you or it create, or possibly some other reading mechanism -// if you go modify the source to replace the FILE * case with some kind -// of callback to your code. (But if you don't support seeking, you may -// just want to go ahead and use pushdata.) - -#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION) -extern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output); -#endif -#if !defined(STB_VORBIS_NO_INTEGER_CONVERSION) -extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output); -#endif -// decode an entire file and output the data interleaved into a malloc()ed -// buffer stored in *output. The return value is the number of samples -// decoded, or -1 if the file could not be opened or was not an ogg vorbis file. -// When you're done with it, just free() the pointer returned in *output. - -extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, - int *error, const stb_vorbis_alloc *alloc_buffer); -// create an ogg vorbis decoder from an ogg vorbis stream in memory (note -// this must be the entire stream!). on failure, returns NULL and sets *error - -#ifndef STB_VORBIS_NO_STDIO -extern stb_vorbis * stb_vorbis_open_filename(const char *filename, - int *error, const stb_vorbis_alloc *alloc_buffer); -// create an ogg vorbis decoder from a filename via fopen(). on failure, -// returns NULL and sets *error (possibly to VORBIS_file_open_failure). - -extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, - int *error, const stb_vorbis_alloc *alloc_buffer); -// create an ogg vorbis decoder from an open FILE *, looking for a stream at -// the _current_ seek point (ftell). on failure, returns NULL and sets *error. -// note that stb_vorbis must "own" this stream; if you seek it in between -// calls to stb_vorbis, it will become confused. Moreover, if you attempt to -// perform stb_vorbis_seek_*() operations on this file, it will assume it -// owns the _entire_ rest of the file after the start point. Use the next -// function, stb_vorbis_open_file_section(), to limit it. - -extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close, - int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len); -// create an ogg vorbis decoder from an open FILE *, looking for a stream at -// the _current_ seek point (ftell); the stream will be of length 'len' bytes. -// on failure, returns NULL and sets *error. note that stb_vorbis must "own" -// this stream; if you seek it in between calls to stb_vorbis, it will become -// confused. -#endif - -extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number); -extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); -// these functions seek in the Vorbis file to (approximately) 'sample_number'. -// after calling seek_frame(), the next call to get_frame_*() will include -// the specified sample. after calling stb_vorbis_seek(), the next call to -// stb_vorbis_get_samples_* will start with the specified sample. If you -// do not need to seek to EXACTLY the target sample when using get_samples_*, -// you can also use seek_frame(). - -extern int stb_vorbis_seek_start(stb_vorbis *f); -// this function is equivalent to stb_vorbis_seek(f,0) - -extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f); -extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f); -// these functions return the total length of the vorbis stream - -extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output); -// decode the next frame and return the number of samples. the number of -// channels returned are stored in *channels (which can be NULL--it is always -// the same as the number of channels reported by get_info). *output will -// contain an array of float* buffers, one per channel. These outputs will -// be overwritten on the next call to stb_vorbis_get_frame_*. -// -// You generally should not intermix calls to stb_vorbis_get_frame_*() -// and stb_vorbis_get_samples_*(), since the latter calls the former. - -#ifndef STB_VORBIS_NO_INTEGER_CONVERSION -extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts); -extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples); -#endif -// decode the next frame and return the number of *samples* per channel. -// Note that for interleaved data, you pass in the number of shorts (the -// size of your array), but the return value is the number of samples per -// channel, not the total number of samples. -// -// The data is coerced to the number of channels you request according to the -// channel coercion rules (see below). You must pass in the size of your -// buffer(s) so that stb_vorbis will not overwrite the end of the buffer. -// The maximum buffer size needed can be gotten from get_info(); however, -// the Vorbis I specification implies an absolute maximum of 4096 samples -// per channel. - -// Channel coercion rules: -// Let M be the number of channels requested, and N the number of channels present, -// and Cn be the nth channel; let stereo L be the sum of all L and center channels, -// and stereo R be the sum of all R and center channels (channel assignment from the -// vorbis spec). -// M N output -// 1 k sum(Ck) for all k -// 2 * stereo L, stereo R -// k l k > l, the first l channels, then 0s -// k l k <= l, the first k channels -// Note that this is not _good_ surround etc. mixing at all! It's just so -// you get something useful. - -extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats); -extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples); -// gets num_samples samples, not necessarily on a frame boundary--this requires -// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES. -// Returns the number of samples stored per channel; it may be less than requested -// at the end of the file. If there are no more samples in the file, returns 0. - -#ifndef STB_VORBIS_NO_INTEGER_CONVERSION -extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts); -extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples); -#endif -// gets num_samples samples, not necessarily on a frame boundary--this requires -// buffering so you have to supply the buffers. Applies the coercion rules above -// to produce 'channels' channels. Returns the number of samples stored per channel; -// it may be less than requested at the end of the file. If there are no more -// samples in the file, returns 0. - -#endif - -//////// ERROR CODES - -enum STBVorbisError -{ - VORBIS__no_error, - - VORBIS_need_more_data=1, // not a real error - - VORBIS_invalid_api_mixing, // can't mix API modes - VORBIS_outofmem, // not enough memory - VORBIS_feature_not_supported, // uses floor 0 - VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small - VORBIS_file_open_failure, // fopen() failed - VORBIS_seek_without_length, // can't seek in unknown-length file - - VORBIS_unexpected_eof=10, // file is truncated? - VORBIS_seek_invalid, // seek past EOF - - // decoding errors (corrupt/invalid stream) -- you probably - // don't care about the exact details of these - - // vorbis errors: - VORBIS_invalid_setup=20, - VORBIS_invalid_stream, - - // ogg errors: - VORBIS_missing_capture_pattern=30, - VORBIS_invalid_stream_structure_version, - VORBIS_continued_packet_flag_invalid, - VORBIS_incorrect_stream_serial_number, - VORBIS_invalid_first_page, - VORBIS_bad_packet_type, - VORBIS_cant_find_last_page, - VORBIS_seek_failed, - VORBIS_ogg_skeleton_not_supported -}; - - -#ifdef __cplusplus -} -#endif - -#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H -// -// HEADER ENDS HERE -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef STB_VORBIS_HEADER_ONLY - -// global configuration settings (e.g. set these in the project/makefile), -// or just set them in this file at the top (although ideally the first few -// should be visible when the header file is compiled too, although it's not -// crucial) - -// STB_VORBIS_NO_PUSHDATA_API -// does not compile the code for the various stb_vorbis_*_pushdata() -// functions -// #define STB_VORBIS_NO_PUSHDATA_API - -// STB_VORBIS_NO_PULLDATA_API -// does not compile the code for the non-pushdata APIs -// #define STB_VORBIS_NO_PULLDATA_API - -// STB_VORBIS_NO_STDIO -// does not compile the code for the APIs that use FILE *s internally -// or externally (implied by STB_VORBIS_NO_PULLDATA_API) -// #define STB_VORBIS_NO_STDIO - -// STB_VORBIS_NO_INTEGER_CONVERSION -// does not compile the code for converting audio sample data from -// float to integer (implied by STB_VORBIS_NO_PULLDATA_API) -// #define STB_VORBIS_NO_INTEGER_CONVERSION - -// STB_VORBIS_NO_FAST_SCALED_FLOAT -// does not use a fast float-to-int trick to accelerate float-to-int on -// most platforms which requires endianness be defined correctly. -//#define STB_VORBIS_NO_FAST_SCALED_FLOAT - - -// STB_VORBIS_MAX_CHANNELS [number] -// globally define this to the maximum number of channels you need. -// The spec does not put a restriction on channels except that -// the count is stored in a byte, so 255 is the hard limit. -// Reducing this saves about 16 bytes per value, so using 16 saves -// (255-16)*16 or around 4KB. Plus anything other memory usage -// I forgot to account for. Can probably go as low as 8 (7.1 audio), -// 6 (5.1 audio), or 2 (stereo only). -#ifndef STB_VORBIS_MAX_CHANNELS -#define STB_VORBIS_MAX_CHANNELS 16 // enough for anyone? -#endif - -// STB_VORBIS_PUSHDATA_CRC_COUNT [number] -// after a flush_pushdata(), stb_vorbis begins scanning for the -// next valid page, without backtracking. when it finds something -// that looks like a page, it streams through it and verifies its -// CRC32. Should that validation fail, it keeps scanning. But it's -// possible that _while_ streaming through to check the CRC32 of -// one candidate page, it sees another candidate page. This #define -// determines how many "overlapping" candidate pages it can search -// at once. Note that "real" pages are typically ~4KB to ~8KB, whereas -// garbage pages could be as big as 64KB, but probably average ~16KB. -// So don't hose ourselves by scanning an apparent 64KB page and -// missing a ton of real ones in the interim; so minimum of 2 -#ifndef STB_VORBIS_PUSHDATA_CRC_COUNT -#define STB_VORBIS_PUSHDATA_CRC_COUNT 4 -#endif - -// STB_VORBIS_FAST_HUFFMAN_LENGTH [number] -// sets the log size of the huffman-acceleration table. Maximum -// supported value is 24. with larger numbers, more decodings are O(1), -// but the table size is larger so worse cache missing, so you'll have -// to probe (and try multiple ogg vorbis files) to find the sweet spot. -#ifndef STB_VORBIS_FAST_HUFFMAN_LENGTH -#define STB_VORBIS_FAST_HUFFMAN_LENGTH 10 -#endif - -// STB_VORBIS_FAST_BINARY_LENGTH [number] -// sets the log size of the binary-search acceleration table. this -// is used in similar fashion to the fast-huffman size to set initial -// parameters for the binary search - -// STB_VORBIS_FAST_HUFFMAN_INT -// The fast huffman tables are much more efficient if they can be -// stored as 16-bit results instead of 32-bit results. This restricts -// the codebooks to having only 65535 possible outcomes, though. -// (At least, accelerated by the huffman table.) -#ifndef STB_VORBIS_FAST_HUFFMAN_INT -#define STB_VORBIS_FAST_HUFFMAN_SHORT -#endif - -// STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH -// If the 'fast huffman' search doesn't succeed, then stb_vorbis falls -// back on binary searching for the correct one. This requires storing -// extra tables with the huffman codes in sorted order. Defining this -// symbol trades off space for speed by forcing a linear search in the -// non-fast case, except for "sparse" codebooks. -// #define STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH - -// STB_VORBIS_DIVIDES_IN_RESIDUE -// stb_vorbis precomputes the result of the scalar residue decoding -// that would otherwise require a divide per chunk. you can trade off -// space for time by defining this symbol. -// #define STB_VORBIS_DIVIDES_IN_RESIDUE - -// STB_VORBIS_DIVIDES_IN_CODEBOOK -// vorbis VQ codebooks can be encoded two ways: with every case explicitly -// stored, or with all elements being chosen from a small range of values, -// and all values possible in all elements. By default, stb_vorbis expands -// this latter kind out to look like the former kind for ease of decoding, -// because otherwise an integer divide-per-vector-element is required to -// unpack the index. If you define STB_VORBIS_DIVIDES_IN_CODEBOOK, you can -// trade off storage for speed. -//#define STB_VORBIS_DIVIDES_IN_CODEBOOK - -#ifdef STB_VORBIS_CODEBOOK_SHORTS -#error "STB_VORBIS_CODEBOOK_SHORTS is no longer supported as it produced incorrect results for some input formats" -#endif - -// STB_VORBIS_DIVIDE_TABLE -// this replaces small integer divides in the floor decode loop with -// table lookups. made less than 1% difference, so disabled by default. - -// STB_VORBIS_NO_INLINE_DECODE -// disables the inlining of the scalar codebook fast-huffman decode. -// might save a little codespace; useful for debugging -// #define STB_VORBIS_NO_INLINE_DECODE - -// STB_VORBIS_NO_DEFER_FLOOR -// Normally we only decode the floor without synthesizing the actual -// full curve. We can instead synthesize the curve immediately. This -// requires more memory and is very likely slower, so I don't think -// you'd ever want to do it except for debugging. -// #define STB_VORBIS_NO_DEFER_FLOOR - - - - -////////////////////////////////////////////////////////////////////////////// - -#ifdef STB_VORBIS_NO_PULLDATA_API - #define STB_VORBIS_NO_INTEGER_CONVERSION - #define STB_VORBIS_NO_STDIO -#endif - -#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) - #define STB_VORBIS_NO_STDIO 1 -#endif - -#ifndef STB_VORBIS_NO_INTEGER_CONVERSION -#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT - - // only need endianness for fast-float-to-int, which we don't - // use for pushdata - - #ifndef STB_VORBIS_BIG_ENDIAN - #define STB_VORBIS_ENDIAN 0 - #else - #define STB_VORBIS_ENDIAN 1 - #endif - -#endif -#endif - - -#ifndef STB_VORBIS_NO_STDIO -#include -#endif - -#ifndef STB_VORBIS_NO_CRT - #include - #include - #include - #include - - // find definition of alloca if it's not in stdlib.h: - #if defined(_MSC_VER) || defined(__MINGW32__) - #include - #endif - #if defined(__linux__) || defined(__linux) || defined(__sun__) || defined(__EMSCRIPTEN__) || defined(__NEWLIB__) - #include - #endif -#else // STB_VORBIS_NO_CRT - #define NULL 0 - #define malloc(s) 0 - #define free(s) ((void) 0) - #define realloc(s) 0 -#endif // STB_VORBIS_NO_CRT - -#include - -#ifdef __MINGW32__ - // eff you mingw: - // "fixed": - // http://sourceforge.net/p/mingw-w64/mailman/message/32882927/ - // "no that broke the build, reverted, who cares about C": - // http://sourceforge.net/p/mingw-w64/mailman/message/32890381/ - #ifdef __forceinline - #undef __forceinline - #endif - #define __forceinline - #ifndef alloca - #define alloca __builtin_alloca - #endif -#elif !defined(_MSC_VER) - #if __GNUC__ - #define __forceinline inline - #else - #define __forceinline - #endif -#endif - -#if STB_VORBIS_MAX_CHANNELS > 256 -#error "Value of STB_VORBIS_MAX_CHANNELS outside of allowed range" -#endif - -#if STB_VORBIS_FAST_HUFFMAN_LENGTH > 24 -#error "Value of STB_VORBIS_FAST_HUFFMAN_LENGTH outside of allowed range" -#endif - - -#if 0 -#include -#define CHECK(f) _CrtIsValidHeapPointer(f->channel_buffers[1]) -#else -#define CHECK(f) ((void) 0) -#endif - -#define MAX_BLOCKSIZE_LOG 13 // from specification -#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG) - - -typedef unsigned char uint8; -typedef signed char int8; -typedef unsigned short uint16; -typedef signed short int16; -typedef unsigned int uint32; -typedef signed int int32; - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -typedef float codetype; - -#ifdef _MSC_VER -#define STBV_NOTUSED(v) (void)(v) -#else -#define STBV_NOTUSED(v) (void)sizeof(v) -#endif - -// @NOTE -// -// Some arrays below are tagged "//varies", which means it's actually -// a variable-sized piece of data, but rather than malloc I assume it's -// small enough it's better to just allocate it all together with the -// main thing -// -// Most of the variables are specified with the smallest size I could pack -// them into. It might give better performance to make them all full-sized -// integers. It should be safe to freely rearrange the structures or change -// the sizes larger--nothing relies on silently truncating etc., nor the -// order of variables. - -#define FAST_HUFFMAN_TABLE_SIZE (1 << STB_VORBIS_FAST_HUFFMAN_LENGTH) -#define FAST_HUFFMAN_TABLE_MASK (FAST_HUFFMAN_TABLE_SIZE - 1) - -typedef struct -{ - int dimensions, entries; - uint8 *codeword_lengths; - float minimum_value; - float delta_value; - uint8 value_bits; - uint8 lookup_type; - uint8 sequence_p; - uint8 sparse; - uint32 lookup_values; - codetype *multiplicands; - uint32 *codewords; - #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT - int16 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; - #else - int32 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; - #endif - uint32 *sorted_codewords; - int *sorted_values; - int sorted_entries; -} Codebook; - -typedef struct -{ - uint8 order; - uint16 rate; - uint16 bark_map_size; - uint8 amplitude_bits; - uint8 amplitude_offset; - uint8 number_of_books; - uint8 book_list[16]; // varies -} Floor0; - -typedef struct -{ - uint8 partitions; - uint8 partition_class_list[32]; // varies - uint8 class_dimensions[16]; // varies - uint8 class_subclasses[16]; // varies - uint8 class_masterbooks[16]; // varies - int16 subclass_books[16][8]; // varies - uint16 Xlist[31*8+2]; // varies - uint8 sorted_order[31*8+2]; - uint8 neighbors[31*8+2][2]; - uint8 floor1_multiplier; - uint8 rangebits; - int values; -} Floor1; - -typedef union -{ - Floor0 floor0; - Floor1 floor1; -} Floor; - -typedef struct -{ - uint32 begin, end; - uint32 part_size; - uint8 classifications; - uint8 classbook; - uint8 **classdata; - int16 (*residue_books)[8]; -} Residue; - -typedef struct -{ - uint8 magnitude; - uint8 angle; - uint8 mux; -} MappingChannel; - -typedef struct -{ - uint16 coupling_steps; - MappingChannel *chan; - uint8 submaps; - uint8 submap_floor[15]; // varies - uint8 submap_residue[15]; // varies -} Mapping; - -typedef struct -{ - uint8 blockflag; - uint8 mapping; - uint16 windowtype; - uint16 transformtype; -} Mode; - -typedef struct -{ - uint32 goal_crc; // expected crc if match - int bytes_left; // bytes left in packet - uint32 crc_so_far; // running crc - int bytes_done; // bytes processed in _current_ chunk - uint32 sample_loc; // granule pos encoded in page -} CRCscan; - -typedef struct -{ - uint32 page_start, page_end; - uint32 last_decoded_sample; -} ProbedPage; - -struct stb_vorbis -{ - // user-accessible info - unsigned int sample_rate; - int channels; - - unsigned int setup_memory_required; - unsigned int temp_memory_required; - unsigned int setup_temp_memory_required; - - char *vendor; - int comment_list_length; - char **comment_list; - - // input config -#ifndef STB_VORBIS_NO_STDIO - FILE *f; - uint32 f_start; - int close_on_free; -#endif - - uint8 *stream; - uint8 *stream_start; - uint8 *stream_end; - - uint32 stream_len; - - uint8 push_mode; - - // the page to seek to when seeking to start, may be zero - uint32 first_audio_page_offset; - - // p_first is the page on which the first audio packet ends - // (but not necessarily the page on which it starts) - ProbedPage p_first, p_last; - - // memory management - stb_vorbis_alloc alloc; - int setup_offset; - int temp_offset; - - // run-time results - int eof; - enum STBVorbisError error; - - // user-useful data - - // header info - int blocksize[2]; - int blocksize_0, blocksize_1; - int codebook_count; - Codebook *codebooks; - int floor_count; - uint16 floor_types[64]; // varies - Floor *floor_config; - int residue_count; - uint16 residue_types[64]; // varies - Residue *residue_config; - int mapping_count; - Mapping *mapping; - int mode_count; - Mode mode_config[64]; // varies - - uint32 total_samples; - - // decode buffer - float *channel_buffers[STB_VORBIS_MAX_CHANNELS]; - float *outputs [STB_VORBIS_MAX_CHANNELS]; - - float *previous_window[STB_VORBIS_MAX_CHANNELS]; - int previous_length; - - #ifndef STB_VORBIS_NO_DEFER_FLOOR - int16 *finalY[STB_VORBIS_MAX_CHANNELS]; - #else - float *floor_buffers[STB_VORBIS_MAX_CHANNELS]; - #endif - - uint32 current_loc; // sample location of next frame to decode - int current_loc_valid; - - // per-blocksize precomputed data - - // twiddle factors - float *A[2],*B[2],*C[2]; - float *window[2]; - uint16 *bit_reverse[2]; - - // current page/packet/segment streaming info - uint32 serial; // stream serial number for verification - int last_page; - int segment_count; - uint8 segments[255]; - uint8 page_flag; - uint8 bytes_in_seg; - uint8 first_decode; - int next_seg; - int last_seg; // flag that we're on the last segment - int last_seg_which; // what was the segment number of the last seg? - uint32 acc; - int valid_bits; - int packet_bytes; - int end_seg_with_known_loc; - uint32 known_loc_for_packet; - int discard_samples_deferred; - uint32 samples_output; - - // push mode scanning - int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching -#ifndef STB_VORBIS_NO_PUSHDATA_API - CRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT]; -#endif - - // sample-access - int channel_buffer_start; - int channel_buffer_end; -}; - -#if defined(STB_VORBIS_NO_PUSHDATA_API) - #define IS_PUSH_MODE(f) FALSE -#elif defined(STB_VORBIS_NO_PULLDATA_API) - #define IS_PUSH_MODE(f) TRUE -#else - #define IS_PUSH_MODE(f) ((f)->push_mode) -#endif - -typedef struct stb_vorbis vorb; - -static int error(vorb *f, enum STBVorbisError e) -{ - f->error = e; - if (!f->eof && e != VORBIS_need_more_data) { - f->error=e; // breakpoint for debugging - } - return 0; -} - - -// these functions are used for allocating temporary memory -// while decoding. if you can afford the stack space, use -// alloca(); otherwise, provide a temp buffer and it will -// allocate out of those. - -#define array_size_required(count,size) (count*(sizeof(void *)+(size))) - -#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size)) -#define temp_free(f,p) (void)0 -#define temp_alloc_save(f) ((f)->temp_offset) -#define temp_alloc_restore(f,p) ((f)->temp_offset = (p)) - -#define temp_block_array(f,count,size) make_block_array(temp_alloc(f,array_size_required(count,size)), count, size) - -// given a sufficiently large block of memory, make an array of pointers to subblocks of it -static void *make_block_array(void *mem, int count, int size) -{ - int i; - void ** p = (void **) mem; - char *q = (char *) (p + count); - for (i=0; i < count; ++i) { - p[i] = q; - q += size; - } - return p; -} - -static void *setup_malloc(vorb *f, int sz) -{ - sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs. - f->setup_memory_required += sz; - if (f->alloc.alloc_buffer) { - void *p = (char *) f->alloc.alloc_buffer + f->setup_offset; - if (f->setup_offset + sz > f->temp_offset) return NULL; - f->setup_offset += sz; - return p; - } - return sz ? malloc(sz) : NULL; -} - -static void setup_free(vorb *f, void *p) -{ - if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack - free(p); -} - -static void *setup_temp_malloc(vorb *f, int sz) -{ - sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs. - if (f->alloc.alloc_buffer) { - if (f->temp_offset - sz < f->setup_offset) return NULL; - f->temp_offset -= sz; - return (char *) f->alloc.alloc_buffer + f->temp_offset; - } - return malloc(sz); -} - -static void setup_temp_free(vorb *f, void *p, int sz) -{ - if (f->alloc.alloc_buffer) { - f->temp_offset += (sz+7)&~7; - return; - } - free(p); -} - -#define CRC32_POLY 0x04c11db7 // from spec - -static uint32 crc_table[256]; -static void crc32_init(void) -{ - int i,j; - uint32 s; - for(i=0; i < 256; i++) { - for (s=(uint32) i << 24, j=0; j < 8; ++j) - s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0); - crc_table[i] = s; - } -} - -static __forceinline uint32 crc32_update(uint32 crc, uint8 byte) -{ - return (crc << 8) ^ crc_table[byte ^ (crc >> 24)]; -} - - -// used in setup, and for huffman that doesn't go fast path -static unsigned int bit_reverse(unsigned int n) -{ - n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1); - n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2); - n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4); - n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8); - return (n >> 16) | (n << 16); -} - -static float square(float x) -{ - return x*x; -} - -// this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3 -// as required by the specification. fast(?) implementation from stb.h -// @OPTIMIZE: called multiple times per-packet with "constants"; move to setup -static int ilog(int32 n) -{ - static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; - - if (n < 0) return 0; // signed n returns 0 - - // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29) - if (n < (1 << 14)) - if (n < (1 << 4)) return 0 + log2_4[n ]; - else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; - else return 10 + log2_4[n >> 10]; - else if (n < (1 << 24)) - if (n < (1 << 19)) return 15 + log2_4[n >> 15]; - else return 20 + log2_4[n >> 20]; - else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; - else return 30 + log2_4[n >> 30]; -} - -#ifndef M_PI - #define M_PI 3.14159265358979323846264f // from CRC -#endif - -// code length assigned to a value with no huffman encoding -#define NO_CODE 255 - -/////////////////////// LEAF SETUP FUNCTIONS ////////////////////////// -// -// these functions are only called at setup, and only a few times -// per file - -static float float32_unpack(uint32 x) -{ - // from the specification - uint32 mantissa = x & 0x1fffff; - uint32 sign = x & 0x80000000; - uint32 exp = (x & 0x7fe00000) >> 21; - double res = sign ? -(double)mantissa : (double)mantissa; - return (float) ldexp((float)res, (int)exp-788); -} - - -// zlib & jpeg huffman tables assume that the output symbols -// can either be arbitrarily arranged, or have monotonically -// increasing frequencies--they rely on the lengths being sorted; -// this makes for a very simple generation algorithm. -// vorbis allows a huffman table with non-sorted lengths. This -// requires a more sophisticated construction, since symbols in -// order do not map to huffman codes "in order". -static void add_entry(Codebook *c, uint32 huff_code, int symbol, int count, int len, uint32 *values) -{ - if (!c->sparse) { - c->codewords [symbol] = huff_code; - } else { - c->codewords [count] = huff_code; - c->codeword_lengths[count] = len; - values [count] = symbol; - } -} - -static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) -{ - int i,k,m=0; - uint32 available[32]; - - memset(available, 0, sizeof(available)); - // find the first entry - for (k=0; k < n; ++k) if (len[k] < NO_CODE) break; - if (k == n) { assert(c->sorted_entries == 0); return TRUE; } - assert(len[k] < 32); // no error return required, code reading lens checks this - // add to the list - add_entry(c, 0, k, m++, len[k], values); - // add all available leaves - for (i=1; i <= len[k]; ++i) - available[i] = 1U << (32-i); - // note that the above code treats the first case specially, - // but it's really the same as the following code, so they - // could probably be combined (except the initial code is 0, - // and I use 0 in available[] to mean 'empty') - for (i=k+1; i < n; ++i) { - uint32 res; - int z = len[i], y; - if (z == NO_CODE) continue; - assert(z < 32); // no error return required, code reading lens checks this - // find lowest available leaf (should always be earliest, - // which is what the specification calls for) - // note that this property, and the fact we can never have - // more than one free leaf at a given level, isn't totally - // trivial to prove, but it seems true and the assert never - // fires, so! - while (z > 0 && !available[z]) --z; - if (z == 0) { return FALSE; } - res = available[z]; - available[z] = 0; - add_entry(c, bit_reverse(res), i, m++, len[i], values); - // propagate availability up the tree - if (z != len[i]) { - for (y=len[i]; y > z; --y) { - assert(available[y] == 0); - available[y] = res + (1 << (32-y)); - } - } - } - return TRUE; -} - -// accelerated huffman table allows fast O(1) match of all symbols -// of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH -static void compute_accelerated_huffman(Codebook *c) -{ - int i, len; - for (i=0; i < FAST_HUFFMAN_TABLE_SIZE; ++i) - c->fast_huffman[i] = -1; - - len = c->sparse ? c->sorted_entries : c->entries; - #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT - if (len > 32767) len = 32767; // largest possible value we can encode! - #endif - for (i=0; i < len; ++i) { - if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) { - uint32 z = c->sparse ? bit_reverse(c->sorted_codewords[i]) : c->codewords[i]; - // set table entries for all bit combinations in the higher bits - while (z < FAST_HUFFMAN_TABLE_SIZE) { - c->fast_huffman[z] = i; - z += 1 << c->codeword_lengths[i]; - } - } - } -} - -#ifdef _MSC_VER -#define STBV_CDECL __cdecl -#else -#define STBV_CDECL -#endif - -static int STBV_CDECL uint32_compare(const void *p, const void *q) -{ - uint32 x = * (uint32 *) p; - uint32 y = * (uint32 *) q; - return x < y ? -1 : x > y; -} - -static int include_in_sort(Codebook *c, uint8 len) -{ - if (c->sparse) { assert(len != NO_CODE); return TRUE; } - if (len == NO_CODE) return FALSE; - if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE; - return FALSE; -} - -// if the fast table above doesn't work, we want to binary -// search them... need to reverse the bits -static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values) -{ - int i, len; - // build a list of all the entries - // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN. - // this is kind of a frivolous optimization--I don't see any performance improvement, - // but it's like 4 extra lines of code, so. - if (!c->sparse) { - int k = 0; - for (i=0; i < c->entries; ++i) - if (include_in_sort(c, lengths[i])) - c->sorted_codewords[k++] = bit_reverse(c->codewords[i]); - assert(k == c->sorted_entries); - } else { - for (i=0; i < c->sorted_entries; ++i) - c->sorted_codewords[i] = bit_reverse(c->codewords[i]); - } - - qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), uint32_compare); - c->sorted_codewords[c->sorted_entries] = 0xffffffff; - - len = c->sparse ? c->sorted_entries : c->entries; - // now we need to indicate how they correspond; we could either - // #1: sort a different data structure that says who they correspond to - // #2: for each sorted entry, search the original list to find who corresponds - // #3: for each original entry, find the sorted entry - // #1 requires extra storage, #2 is slow, #3 can use binary search! - for (i=0; i < len; ++i) { - int huff_len = c->sparse ? lengths[values[i]] : lengths[i]; - if (include_in_sort(c,huff_len)) { - uint32 code = bit_reverse(c->codewords[i]); - int x=0, n=c->sorted_entries; - while (n > 1) { - // invariant: sc[x] <= code < sc[x+n] - int m = x + (n >> 1); - if (c->sorted_codewords[m] <= code) { - x = m; - n -= (n>>1); - } else { - n >>= 1; - } - } - assert(c->sorted_codewords[x] == code); - if (c->sparse) { - c->sorted_values[x] = values[i]; - c->codeword_lengths[x] = huff_len; - } else { - c->sorted_values[x] = i; - } - } - } -} - -// only run while parsing the header (3 times) -static int vorbis_validate(uint8 *data) -{ - static uint8 vorbis[6] = { 'v', 'o', 'r', 'b', 'i', 's' }; - return memcmp(data, vorbis, 6) == 0; -} - -// called from setup only, once per code book -// (formula implied by specification) -static int lookup1_values(int entries, int dim) -{ - int r = (int) floor(exp((float) log((float) entries) / dim)); - if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning; - ++r; // floor() to avoid _ftol() when non-CRT - if (pow((float) r+1, dim) <= entries) - return -1; - if ((int) floor(pow((float) r, dim)) > entries) - return -1; - return r; -} - -// called twice per file -static void compute_twiddle_factors(int n, float *A, float *B, float *C) -{ - int n4 = n >> 2, n8 = n >> 3; - int k,k2; - - for (k=k2=0; k < n4; ++k,k2+=2) { - A[k2 ] = (float) cos(4*k*M_PI/n); - A[k2+1] = (float) -sin(4*k*M_PI/n); - B[k2 ] = (float) cos((k2+1)*M_PI/n/2) * 0.5f; - B[k2+1] = (float) sin((k2+1)*M_PI/n/2) * 0.5f; - } - for (k=k2=0; k < n8; ++k,k2+=2) { - C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); - C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); - } -} - -static void compute_window(int n, float *window) -{ - int n2 = n >> 1, i; - for (i=0; i < n2; ++i) - window[i] = (float) sin(0.5 * M_PI * square((float) sin((i - 0 + 0.5) / n2 * 0.5 * M_PI))); -} - -static void compute_bitreverse(int n, uint16 *rev) -{ - int ld = ilog(n) - 1; // ilog is off-by-one from normal definitions - int i, n8 = n >> 3; - for (i=0; i < n8; ++i) - rev[i] = (bit_reverse(i) >> (32-ld+3)) << 2; -} - -static int init_blocksize(vorb *f, int b, int n) -{ - int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3; - f->A[b] = (float *) setup_malloc(f, sizeof(float) * n2); - f->B[b] = (float *) setup_malloc(f, sizeof(float) * n2); - f->C[b] = (float *) setup_malloc(f, sizeof(float) * n4); - if (!f->A[b] || !f->B[b] || !f->C[b]) return error(f, VORBIS_outofmem); - compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]); - f->window[b] = (float *) setup_malloc(f, sizeof(float) * n2); - if (!f->window[b]) return error(f, VORBIS_outofmem); - compute_window(n, f->window[b]); - f->bit_reverse[b] = (uint16 *) setup_malloc(f, sizeof(uint16) * n8); - if (!f->bit_reverse[b]) return error(f, VORBIS_outofmem); - compute_bitreverse(n, f->bit_reverse[b]); - return TRUE; -} - -static void neighbors(uint16 *x, int n, int *plow, int *phigh) -{ - int low = -1; - int high = 65536; - int i; - for (i=0; i < n; ++i) { - if (x[i] > low && x[i] < x[n]) { *plow = i; low = x[i]; } - if (x[i] < high && x[i] > x[n]) { *phigh = i; high = x[i]; } - } -} - -// this has been repurposed so y is now the original index instead of y -typedef struct -{ - uint16 x,id; -} stbv__floor_ordering; - -static int STBV_CDECL point_compare(const void *p, const void *q) -{ - stbv__floor_ordering *a = (stbv__floor_ordering *) p; - stbv__floor_ordering *b = (stbv__floor_ordering *) q; - return a->x < b->x ? -1 : a->x > b->x; -} - -// -/////////////////////// END LEAF SETUP FUNCTIONS ////////////////////////// - - -#if defined(STB_VORBIS_NO_STDIO) - #define USE_MEMORY(z) TRUE -#else - #define USE_MEMORY(z) ((z)->stream) -#endif - -static uint8 get8(vorb *z) -{ - if (USE_MEMORY(z)) { - if (z->stream >= z->stream_end) { z->eof = TRUE; return 0; } - return *z->stream++; - } - - #ifndef STB_VORBIS_NO_STDIO - { - int c = fgetc(z->f); - if (c == EOF) { z->eof = TRUE; return 0; } - return c; - } - #endif -} - -static uint32 get32(vorb *f) -{ - uint32 x; - x = get8(f); - x += get8(f) << 8; - x += get8(f) << 16; - x += (uint32) get8(f) << 24; - return x; -} - -static int getn(vorb *z, uint8 *data, int n) -{ - if (USE_MEMORY(z)) { - if (z->stream+n > z->stream_end) { z->eof = 1; return 0; } - memcpy(data, z->stream, n); - z->stream += n; - return 1; - } - - #ifndef STB_VORBIS_NO_STDIO - if (fread(data, n, 1, z->f) == 1) - return 1; - else { - z->eof = 1; - return 0; - } - #endif -} - -static void skip(vorb *z, int n) -{ - if (USE_MEMORY(z)) { - z->stream += n; - if (z->stream >= z->stream_end) z->eof = 1; - return; - } - #ifndef STB_VORBIS_NO_STDIO - { - long x = ftell(z->f); - fseek(z->f, x+n, SEEK_SET); - } - #endif -} - -static int set_file_offset(stb_vorbis *f, unsigned int loc) -{ - #ifndef STB_VORBIS_NO_PUSHDATA_API - if (f->push_mode) return 0; - #endif - f->eof = 0; - if (USE_MEMORY(f)) { - if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) { - f->stream = f->stream_end; - f->eof = 1; - return 0; - } else { - f->stream = f->stream_start + loc; - return 1; - } - } - #ifndef STB_VORBIS_NO_STDIO - if (loc + f->f_start < loc || loc >= 0x80000000) { - loc = 0x7fffffff; - f->eof = 1; - } else { - loc += f->f_start; - } - if (!fseek(f->f, loc, SEEK_SET)) - return 1; - f->eof = 1; - fseek(f->f, f->f_start, SEEK_END); - return 0; - #endif -} - - -static uint8 ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 }; - -static int capture_pattern(vorb *f) -{ - if (0x4f != get8(f)) return FALSE; - if (0x67 != get8(f)) return FALSE; - if (0x67 != get8(f)) return FALSE; - if (0x53 != get8(f)) return FALSE; - return TRUE; -} - -#define PAGEFLAG_continued_packet 1 -#define PAGEFLAG_first_page 2 -#define PAGEFLAG_last_page 4 - -static int start_page_no_capturepattern(vorb *f) -{ - uint32 loc0,loc1,n; - if (f->first_decode && !IS_PUSH_MODE(f)) { - f->p_first.page_start = stb_vorbis_get_file_offset(f) - 4; - } - // stream structure version - if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version); - // header flag - f->page_flag = get8(f); - // absolute granule position - loc0 = get32(f); - loc1 = get32(f); - // @TODO: validate loc0,loc1 as valid positions? - // stream serial number -- vorbis doesn't interleave, so discard - get32(f); - //if (f->serial != get32(f)) return error(f, VORBIS_incorrect_stream_serial_number); - // page sequence number - n = get32(f); - f->last_page = n; - // CRC32 - get32(f); - // page_segments - f->segment_count = get8(f); - if (!getn(f, f->segments, f->segment_count)) - return error(f, VORBIS_unexpected_eof); - // assume we _don't_ know any the sample position of any segments - f->end_seg_with_known_loc = -2; - if (loc0 != ~0U || loc1 != ~0U) { - int i; - // determine which packet is the last one that will complete - for (i=f->segment_count-1; i >= 0; --i) - if (f->segments[i] < 255) - break; - // 'i' is now the index of the _last_ segment of a packet that ends - if (i >= 0) { - f->end_seg_with_known_loc = i; - f->known_loc_for_packet = loc0; - } - } - if (f->first_decode) { - int i,len; - len = 0; - for (i=0; i < f->segment_count; ++i) - len += f->segments[i]; - len += 27 + f->segment_count; - f->p_first.page_end = f->p_first.page_start + len; - f->p_first.last_decoded_sample = loc0; - } - f->next_seg = 0; - return TRUE; -} - -static int start_page(vorb *f) -{ - if (!capture_pattern(f)) return error(f, VORBIS_missing_capture_pattern); - return start_page_no_capturepattern(f); -} - -static int start_packet(vorb *f) -{ - while (f->next_seg == -1) { - if (!start_page(f)) return FALSE; - if (f->page_flag & PAGEFLAG_continued_packet) - return error(f, VORBIS_continued_packet_flag_invalid); - } - f->last_seg = FALSE; - f->valid_bits = 0; - f->packet_bytes = 0; - f->bytes_in_seg = 0; - // f->next_seg is now valid - return TRUE; -} - -static int maybe_start_packet(vorb *f) -{ - if (f->next_seg == -1) { - int x = get8(f); - if (f->eof) return FALSE; // EOF at page boundary is not an error! - if (0x4f != x ) return error(f, VORBIS_missing_capture_pattern); - if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); - if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); - if (0x53 != get8(f)) return error(f, VORBIS_missing_capture_pattern); - if (!start_page_no_capturepattern(f)) return FALSE; - if (f->page_flag & PAGEFLAG_continued_packet) { - // set up enough state that we can read this packet if we want, - // e.g. during recovery - f->last_seg = FALSE; - f->bytes_in_seg = 0; - return error(f, VORBIS_continued_packet_flag_invalid); - } - } - return start_packet(f); -} - -static int next_segment(vorb *f) -{ - int len; - if (f->last_seg) return 0; - if (f->next_seg == -1) { - f->last_seg_which = f->segment_count-1; // in case start_page fails - if (!start_page(f)) { f->last_seg = 1; return 0; } - if (!(f->page_flag & PAGEFLAG_continued_packet)) return error(f, VORBIS_continued_packet_flag_invalid); - } - len = f->segments[f->next_seg++]; - if (len < 255) { - f->last_seg = TRUE; - f->last_seg_which = f->next_seg-1; - } - if (f->next_seg >= f->segment_count) - f->next_seg = -1; - assert(f->bytes_in_seg == 0); - f->bytes_in_seg = len; - return len; -} - -#define EOP (-1) -#define INVALID_BITS (-1) - -static int get8_packet_raw(vorb *f) -{ - if (!f->bytes_in_seg) { // CLANG! - if (f->last_seg) return EOP; - else if (!next_segment(f)) return EOP; - } - assert(f->bytes_in_seg > 0); - --f->bytes_in_seg; - ++f->packet_bytes; - return get8(f); -} - -static int get8_packet(vorb *f) -{ - int x = get8_packet_raw(f); - f->valid_bits = 0; - return x; -} - -static int get32_packet(vorb *f) -{ - uint32 x; - x = get8_packet(f); - x += get8_packet(f) << 8; - x += get8_packet(f) << 16; - x += (uint32) get8_packet(f) << 24; - return x; -} - -static void flush_packet(vorb *f) -{ - while (get8_packet_raw(f) != EOP); -} - -// @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important -// as the huffman decoder? -static uint32 get_bits(vorb *f, int n) -{ - uint32 z; - - if (f->valid_bits < 0) return 0; - if (f->valid_bits < n) { - if (n > 24) { - // the accumulator technique below would not work correctly in this case - z = get_bits(f, 24); - z += get_bits(f, n-24) << 24; - return z; - } - if (f->valid_bits == 0) f->acc = 0; - while (f->valid_bits < n) { - int z = get8_packet_raw(f); - if (z == EOP) { - f->valid_bits = INVALID_BITS; - return 0; - } - f->acc += z << f->valid_bits; - f->valid_bits += 8; - } - } - - assert(f->valid_bits >= n); - z = f->acc & ((1 << n)-1); - f->acc >>= n; - f->valid_bits -= n; - return z; -} - -// @OPTIMIZE: primary accumulator for huffman -// expand the buffer to as many bits as possible without reading off end of packet -// it might be nice to allow f->valid_bits and f->acc to be stored in registers, -// e.g. cache them locally and decode locally -static __forceinline void prep_huffman(vorb *f) -{ - if (f->valid_bits <= 24) { - if (f->valid_bits == 0) f->acc = 0; - do { - int z; - if (f->last_seg && !f->bytes_in_seg) return; - z = get8_packet_raw(f); - if (z == EOP) return; - f->acc += (unsigned) z << f->valid_bits; - f->valid_bits += 8; - } while (f->valid_bits <= 24); - } -} - -enum -{ - VORBIS_packet_id = 1, - VORBIS_packet_comment = 3, - VORBIS_packet_setup = 5 -}; - -static int codebook_decode_scalar_raw(vorb *f, Codebook *c) -{ - int i; - prep_huffman(f); - - if (c->codewords == NULL && c->sorted_codewords == NULL) - return -1; - - // cases to use binary search: sorted_codewords && !c->codewords - // sorted_codewords && c->entries > 8 - if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) { - // binary search - uint32 code = bit_reverse(f->acc); - int x=0, n=c->sorted_entries, len; - - while (n > 1) { - // invariant: sc[x] <= code < sc[x+n] - int m = x + (n >> 1); - if (c->sorted_codewords[m] <= code) { - x = m; - n -= (n>>1); - } else { - n >>= 1; - } - } - // x is now the sorted index - if (!c->sparse) x = c->sorted_values[x]; - // x is now sorted index if sparse, or symbol otherwise - len = c->codeword_lengths[x]; - if (f->valid_bits >= len) { - f->acc >>= len; - f->valid_bits -= len; - return x; - } - - f->valid_bits = 0; - return -1; - } - - // if small, linear search - assert(!c->sparse); - for (i=0; i < c->entries; ++i) { - if (c->codeword_lengths[i] == NO_CODE) continue; - if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) { - if (f->valid_bits >= c->codeword_lengths[i]) { - f->acc >>= c->codeword_lengths[i]; - f->valid_bits -= c->codeword_lengths[i]; - return i; - } - f->valid_bits = 0; - return -1; - } - } - - error(f, VORBIS_invalid_stream); - f->valid_bits = 0; - return -1; -} - -#ifndef STB_VORBIS_NO_INLINE_DECODE - -#define DECODE_RAW(var, f,c) \ - if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) \ - prep_huffman(f); \ - var = f->acc & FAST_HUFFMAN_TABLE_MASK; \ - var = c->fast_huffman[var]; \ - if (var >= 0) { \ - int n = c->codeword_lengths[var]; \ - f->acc >>= n; \ - f->valid_bits -= n; \ - if (f->valid_bits < 0) { f->valid_bits = 0; var = -1; } \ - } else { \ - var = codebook_decode_scalar_raw(f,c); \ - } - -#else - -static int codebook_decode_scalar(vorb *f, Codebook *c) -{ - int i; - if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) - prep_huffman(f); - // fast huffman table lookup - i = f->acc & FAST_HUFFMAN_TABLE_MASK; - i = c->fast_huffman[i]; - if (i >= 0) { - f->acc >>= c->codeword_lengths[i]; - f->valid_bits -= c->codeword_lengths[i]; - if (f->valid_bits < 0) { f->valid_bits = 0; return -1; } - return i; - } - return codebook_decode_scalar_raw(f,c); -} - -#define DECODE_RAW(var,f,c) var = codebook_decode_scalar(f,c); - -#endif - -#define DECODE(var,f,c) \ - DECODE_RAW(var,f,c) \ - if (c->sparse) var = c->sorted_values[var]; - -#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - #define DECODE_VQ(var,f,c) DECODE_RAW(var,f,c) -#else - #define DECODE_VQ(var,f,c) DECODE(var,f,c) -#endif - - - - - - -// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case -// where we avoid one addition -#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) -#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) -#define CODEBOOK_ELEMENT_BASE(c) (0) - -static int codebook_decode_start(vorb *f, Codebook *c) -{ - int z = -1; - - // type 0 is only legal in a scalar context - if (c->lookup_type == 0) - error(f, VORBIS_invalid_stream); - else { - DECODE_VQ(z,f,c); - if (c->sparse) assert(z < c->sorted_entries); - if (z < 0) { // check for EOP - if (!f->bytes_in_seg) - if (f->last_seg) - return z; - error(f, VORBIS_invalid_stream); - } - } - return z; -} - -static int codebook_decode(vorb *f, Codebook *c, float *output, int len) -{ - int i,z = codebook_decode_start(f,c); - if (z < 0) return FALSE; - if (len > c->dimensions) len = c->dimensions; - -#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (c->lookup_type == 1) { - float last = CODEBOOK_ELEMENT_BASE(c); - int div = 1; - for (i=0; i < len; ++i) { - int off = (z / div) % c->lookup_values; - float val = CODEBOOK_ELEMENT_FAST(c,off) + last; - output[i] += val; - if (c->sequence_p) last = val + c->minimum_value; - div *= c->lookup_values; - } - return TRUE; - } -#endif - - z *= c->dimensions; - if (c->sequence_p) { - float last = CODEBOOK_ELEMENT_BASE(c); - for (i=0; i < len; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - output[i] += val; - last = val + c->minimum_value; - } - } else { - float last = CODEBOOK_ELEMENT_BASE(c); - for (i=0; i < len; ++i) { - output[i] += CODEBOOK_ELEMENT_FAST(c,z+i) + last; - } - } - - return TRUE; -} - -static int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, int step) -{ - int i,z = codebook_decode_start(f,c); - float last = CODEBOOK_ELEMENT_BASE(c); - if (z < 0) return FALSE; - if (len > c->dimensions) len = c->dimensions; - -#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (c->lookup_type == 1) { - int div = 1; - for (i=0; i < len; ++i) { - int off = (z / div) % c->lookup_values; - float val = CODEBOOK_ELEMENT_FAST(c,off) + last; - output[i*step] += val; - if (c->sequence_p) last = val; - div *= c->lookup_values; - } - return TRUE; - } -#endif - - z *= c->dimensions; - for (i=0; i < len; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - output[i*step] += val; - if (c->sequence_p) last = val; - } - - return TRUE; -} - -static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode) -{ - int c_inter = *c_inter_p; - int p_inter = *p_inter_p; - int i,z, effective = c->dimensions; - - // type 0 is only legal in a scalar context - if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); - - while (total_decode > 0) { - float last = CODEBOOK_ELEMENT_BASE(c); - DECODE_VQ(z,f,c); - #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - assert(!c->sparse || z < c->sorted_entries); - #endif - if (z < 0) { - if (!f->bytes_in_seg) - if (f->last_seg) return FALSE; - return error(f, VORBIS_invalid_stream); - } - - // if this will take us off the end of the buffers, stop short! - // we check by computing the length of the virtual interleaved - // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), - // and the length we'll be using (effective) - if (c_inter + p_inter*ch + effective > len * ch) { - effective = len*ch - (p_inter*ch - c_inter); - } - - #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (c->lookup_type == 1) { - int div = 1; - for (i=0; i < effective; ++i) { - int off = (z / div) % c->lookup_values; - float val = CODEBOOK_ELEMENT_FAST(c,off) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == ch) { c_inter = 0; ++p_inter; } - if (c->sequence_p) last = val; - div *= c->lookup_values; - } - } else - #endif - { - z *= c->dimensions; - if (c->sequence_p) { - for (i=0; i < effective; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == ch) { c_inter = 0; ++p_inter; } - last = val; - } - } else { - for (i=0; i < effective; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == ch) { c_inter = 0; ++p_inter; } - } - } - } - - total_decode -= effective; - } - *c_inter_p = c_inter; - *p_inter_p = p_inter; - return TRUE; -} - -static int predict_point(int x, int x0, int x1, int y0, int y1) -{ - int dy = y1 - y0; - int adx = x1 - x0; - // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86? - int err = abs(dy) * (x - x0); - int off = err / adx; - return dy < 0 ? y0 - off : y0 + off; -} - -// the following table is block-copied from the specification -static float inverse_db_table[256] = -{ - 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, - 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, - 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, - 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, - 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, - 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, - 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, - 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, - 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, - 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, - 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, - 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, - 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, - 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, - 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, - 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, - 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, - 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, - 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, - 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, - 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, - 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, - 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, - 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, - 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, - 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, - 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, - 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, - 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, - 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, - 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, - 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, - 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, - 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, - 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, - 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, - 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, - 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, - 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, - 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, - 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, - 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, - 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, - 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, - 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, - 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, - 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, - 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, - 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, - 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, - 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, - 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, - 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, - 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, - 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, - 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, - 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, - 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, - 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, - 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, - 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, - 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, - 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, - 0.82788260f, 0.88168307f, 0.9389798f, 1.0f -}; - - -// @OPTIMIZE: if you want to replace this bresenham line-drawing routine, -// note that you must produce bit-identical output to decode correctly; -// this specific sequence of operations is specified in the spec (it's -// drawing integer-quantized frequency-space lines that the encoder -// expects to be exactly the same) -// ... also, isn't the whole point of Bresenham's algorithm to NOT -// have to divide in the setup? sigh. -#ifndef STB_VORBIS_NO_DEFER_FLOOR -#define LINE_OP(a,b) a *= b -#else -#define LINE_OP(a,b) a = b -#endif - -#ifdef STB_VORBIS_DIVIDE_TABLE -#define DIVTAB_NUMER 32 -#define DIVTAB_DENOM 64 -int8 integer_divide_table[DIVTAB_NUMER][DIVTAB_DENOM]; // 2KB -#endif - -static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y1, int n) -{ - int dy = y1 - y0; - int adx = x1 - x0; - int ady = abs(dy); - int base; - int x=x0,y=y0; - int err = 0; - int sy; - -#ifdef STB_VORBIS_DIVIDE_TABLE - if (adx < DIVTAB_DENOM && ady < DIVTAB_NUMER) { - if (dy < 0) { - base = -integer_divide_table[ady][adx]; - sy = base-1; - } else { - base = integer_divide_table[ady][adx]; - sy = base+1; - } - } else { - base = dy / adx; - if (dy < 0) - sy = base - 1; - else - sy = base+1; - } -#else - base = dy / adx; - if (dy < 0) - sy = base - 1; - else - sy = base+1; -#endif - ady -= abs(base) * adx; - if (x1 > n) x1 = n; - if (x < x1) { - LINE_OP(output[x], inverse_db_table[y&255]); - for (++x; x < x1; ++x) { - err += ady; - if (err >= adx) { - err -= adx; - y += sy; - } else - y += base; - LINE_OP(output[x], inverse_db_table[y&255]); - } - } -} - -static int residue_decode(vorb *f, Codebook *book, float *target, int offset, int n, int rtype) -{ - int k; - if (rtype == 0) { - int step = n / book->dimensions; - for (k=0; k < step; ++k) - if (!codebook_decode_step(f, book, target+offset+k, n-offset-k, step)) - return FALSE; - } else { - for (k=0; k < n; ) { - if (!codebook_decode(f, book, target+offset, n-k)) - return FALSE; - k += book->dimensions; - offset += book->dimensions; - } - } - return TRUE; -} - -// n is 1/2 of the blocksize -- -// specification: "Correct per-vector decode length is [n]/2" -static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) -{ - int i,j,pass; - Residue *r = f->residue_config + rn; - int rtype = f->residue_types[rn]; - int c = r->classbook; - int classwords = f->codebooks[c].dimensions; - unsigned int actual_size = rtype == 2 ? n*2 : n; - unsigned int limit_r_begin = (r->begin < actual_size ? r->begin : actual_size); - unsigned int limit_r_end = (r->end < actual_size ? r->end : actual_size); - int n_read = limit_r_end - limit_r_begin; - int part_read = n_read / r->part_size; - int temp_alloc_point = temp_alloc_save(f); - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - uint8 ***part_classdata = (uint8 ***) temp_block_array(f,f->channels, part_read * sizeof(**part_classdata)); - #else - int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications)); - #endif - - CHECK(f); - - for (i=0; i < ch; ++i) - if (!do_not_decode[i]) - memset(residue_buffers[i], 0, sizeof(float) * n); - - if (rtype == 2 && ch != 1) { - for (j=0; j < ch; ++j) - if (!do_not_decode[j]) - break; - if (j == ch) - goto done; - - for (pass=0; pass < 8; ++pass) { - int pcount = 0, class_set = 0; - if (ch == 2) { - while (pcount < part_read) { - int z = r->begin + pcount*r->part_size; - int c_inter = (z & 1), p_inter = z>>1; - if (pass == 0) { - Codebook *c = f->codebooks+r->classbook; - int q; - DECODE(q,f,c); - if (q == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[0][class_set] = r->classdata[q]; - #else - for (i=classwords-1; i >= 0; --i) { - classifications[0][i+pcount] = q % r->classifications; - q /= r->classifications; - } - #endif - } - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - int z = r->begin + pcount*r->part_size; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[0][class_set][i]; - #else - int c = classifications[0][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - Codebook *book = f->codebooks + b; - #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) - goto done; - #else - // saves 1% - if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) - goto done; - #endif - } else { - z += r->part_size; - c_inter = z & 1; - p_inter = z >> 1; - } - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } else if (ch > 2) { - while (pcount < part_read) { - int z = r->begin + pcount*r->part_size; - int c_inter = z % ch, p_inter = z/ch; - if (pass == 0) { - Codebook *c = f->codebooks+r->classbook; - int q; - DECODE(q,f,c); - if (q == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[0][class_set] = r->classdata[q]; - #else - for (i=classwords-1; i >= 0; --i) { - classifications[0][i+pcount] = q % r->classifications; - q /= r->classifications; - } - #endif - } - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - int z = r->begin + pcount*r->part_size; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[0][class_set][i]; - #else - int c = classifications[0][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - Codebook *book = f->codebooks + b; - if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) - goto done; - } else { - z += r->part_size; - c_inter = z % ch; - p_inter = z / ch; - } - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } - } - goto done; - } - CHECK(f); - - for (pass=0; pass < 8; ++pass) { - int pcount = 0, class_set=0; - while (pcount < part_read) { - if (pass == 0) { - for (j=0; j < ch; ++j) { - if (!do_not_decode[j]) { - Codebook *c = f->codebooks+r->classbook; - int temp; - DECODE(temp,f,c); - if (temp == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[j][class_set] = r->classdata[temp]; - #else - for (i=classwords-1; i >= 0; --i) { - classifications[j][i+pcount] = temp % r->classifications; - temp /= r->classifications; - } - #endif - } - } - } - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - for (j=0; j < ch; ++j) { - if (!do_not_decode[j]) { - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[j][class_set][i]; - #else - int c = classifications[j][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - float *target = residue_buffers[j]; - int offset = r->begin + pcount * r->part_size; - int n = r->part_size; - Codebook *book = f->codebooks + b; - if (!residue_decode(f, book, target, offset, n, rtype)) - goto done; - } - } - } - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } - done: - CHECK(f); - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - temp_free(f,part_classdata); - #else - temp_free(f,classifications); - #endif - temp_alloc_restore(f,temp_alloc_point); -} - - -#if 0 -// slow way for debugging -void inverse_mdct_slow(float *buffer, int n) -{ - int i,j; - int n2 = n >> 1; - float *x = (float *) malloc(sizeof(*x) * n2); - memcpy(x, buffer, sizeof(*x) * n2); - for (i=0; i < n; ++i) { - float acc = 0; - for (j=0; j < n2; ++j) - // formula from paper: - //acc += n/4.0f * x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); - // formula from wikipedia - //acc += 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); - // these are equivalent, except the formula from the paper inverts the multiplier! - // however, what actually works is NO MULTIPLIER!?! - //acc += 64 * 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); - acc += x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); - buffer[i] = acc; - } - free(x); -} -#elif 0 -// same as above, but just barely able to run in real time on modern machines -void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) -{ - float mcos[16384]; - int i,j; - int n2 = n >> 1, nmask = (n << 2) -1; - float *x = (float *) malloc(sizeof(*x) * n2); - memcpy(x, buffer, sizeof(*x) * n2); - for (i=0; i < 4*n; ++i) - mcos[i] = (float) cos(M_PI / 2 * i / n); - - for (i=0; i < n; ++i) { - float acc = 0; - for (j=0; j < n2; ++j) - acc += x[j] * mcos[(2 * i + 1 + n2)*(2*j+1) & nmask]; - buffer[i] = acc; - } - free(x); -} -#elif 0 -// transform to use a slow dct-iv; this is STILL basically trivial, -// but only requires half as many ops -void dct_iv_slow(float *buffer, int n) -{ - float mcos[16384]; - float x[2048]; - int i,j; - int n2 = n >> 1, nmask = (n << 3) - 1; - memcpy(x, buffer, sizeof(*x) * n); - for (i=0; i < 8*n; ++i) - mcos[i] = (float) cos(M_PI / 4 * i / n); - for (i=0; i < n; ++i) { - float acc = 0; - for (j=0; j < n; ++j) - acc += x[j] * mcos[((2 * i + 1)*(2*j+1)) & nmask]; - buffer[i] = acc; - } -} - -void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) -{ - int i, n4 = n >> 2, n2 = n >> 1, n3_4 = n - n4; - float temp[4096]; - - memcpy(temp, buffer, n2 * sizeof(float)); - dct_iv_slow(temp, n2); // returns -c'-d, a-b' - - for (i=0; i < n4 ; ++i) buffer[i] = temp[i+n4]; // a-b' - for ( ; i < n3_4; ++i) buffer[i] = -temp[n3_4 - i - 1]; // b-a', c+d' - for ( ; i < n ; ++i) buffer[i] = -temp[i - n3_4]; // c'+d -} -#endif - -#ifndef LIBVORBIS_MDCT -#define LIBVORBIS_MDCT 0 -#endif - -#if LIBVORBIS_MDCT -// directly call the vorbis MDCT using an interface documented -// by Jeff Roberts... useful for performance comparison -typedef struct -{ - int n; - int log2n; - - float *trig; - int *bitrev; - - float scale; -} mdct_lookup; - -extern void mdct_init(mdct_lookup *lookup, int n); -extern void mdct_clear(mdct_lookup *l); -extern void mdct_backward(mdct_lookup *init, float *in, float *out); - -mdct_lookup M1,M2; - -void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) -{ - mdct_lookup *M; - if (M1.n == n) M = &M1; - else if (M2.n == n) M = &M2; - else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; } - else { - if (M2.n) __asm int 3; - mdct_init(&M2, n); - M = &M2; - } - - mdct_backward(M, buffer, buffer); -} -#endif - - -// the following were split out into separate functions while optimizing; -// they could be pushed back up but eh. __forceinline showed no change; -// they're probably already being inlined. -static void imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A) -{ - float *ee0 = e + i_off; - float *ee2 = ee0 + k_off; - int i; - - assert((n & 3) == 0); - for (i=(n>>2); i > 0; --i) { - float k00_20, k01_21; - k00_20 = ee0[ 0] - ee2[ 0]; - k01_21 = ee0[-1] - ee2[-1]; - ee0[ 0] += ee2[ 0];//ee0[ 0] = ee0[ 0] + ee2[ 0]; - ee0[-1] += ee2[-1];//ee0[-1] = ee0[-1] + ee2[-1]; - ee2[ 0] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-1] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; - - k00_20 = ee0[-2] - ee2[-2]; - k01_21 = ee0[-3] - ee2[-3]; - ee0[-2] += ee2[-2];//ee0[-2] = ee0[-2] + ee2[-2]; - ee0[-3] += ee2[-3];//ee0[-3] = ee0[-3] + ee2[-3]; - ee2[-2] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-3] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; - - k00_20 = ee0[-4] - ee2[-4]; - k01_21 = ee0[-5] - ee2[-5]; - ee0[-4] += ee2[-4];//ee0[-4] = ee0[-4] + ee2[-4]; - ee0[-5] += ee2[-5];//ee0[-5] = ee0[-5] + ee2[-5]; - ee2[-4] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-5] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; - - k00_20 = ee0[-6] - ee2[-6]; - k01_21 = ee0[-7] - ee2[-7]; - ee0[-6] += ee2[-6];//ee0[-6] = ee0[-6] + ee2[-6]; - ee0[-7] += ee2[-7];//ee0[-7] = ee0[-7] + ee2[-7]; - ee2[-6] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-7] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; - ee0 -= 8; - ee2 -= 8; - } -} - -static void imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1) -{ - int i; - float k00_20, k01_21; - - float *e0 = e + d0; - float *e2 = e0 + k_off; - - for (i=lim >> 2; i > 0; --i) { - k00_20 = e0[-0] - e2[-0]; - k01_21 = e0[-1] - e2[-1]; - e0[-0] += e2[-0];//e0[-0] = e0[-0] + e2[-0]; - e0[-1] += e2[-1];//e0[-1] = e0[-1] + e2[-1]; - e2[-0] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-1] = (k01_21)*A[0] + (k00_20) * A[1]; - - A += k1; - - k00_20 = e0[-2] - e2[-2]; - k01_21 = e0[-3] - e2[-3]; - e0[-2] += e2[-2];//e0[-2] = e0[-2] + e2[-2]; - e0[-3] += e2[-3];//e0[-3] = e0[-3] + e2[-3]; - e2[-2] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-3] = (k01_21)*A[0] + (k00_20) * A[1]; - - A += k1; - - k00_20 = e0[-4] - e2[-4]; - k01_21 = e0[-5] - e2[-5]; - e0[-4] += e2[-4];//e0[-4] = e0[-4] + e2[-4]; - e0[-5] += e2[-5];//e0[-5] = e0[-5] + e2[-5]; - e2[-4] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-5] = (k01_21)*A[0] + (k00_20) * A[1]; - - A += k1; - - k00_20 = e0[-6] - e2[-6]; - k01_21 = e0[-7] - e2[-7]; - e0[-6] += e2[-6];//e0[-6] = e0[-6] + e2[-6]; - e0[-7] += e2[-7];//e0[-7] = e0[-7] + e2[-7]; - e2[-6] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-7] = (k01_21)*A[0] + (k00_20) * A[1]; - - e0 -= 8; - e2 -= 8; - - A += k1; - } -} - -static void imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0) -{ - int i; - float A0 = A[0]; - float A1 = A[0+1]; - float A2 = A[0+a_off]; - float A3 = A[0+a_off+1]; - float A4 = A[0+a_off*2+0]; - float A5 = A[0+a_off*2+1]; - float A6 = A[0+a_off*3+0]; - float A7 = A[0+a_off*3+1]; - - float k00,k11; - - float *ee0 = e +i_off; - float *ee2 = ee0+k_off; - - for (i=n; i > 0; --i) { - k00 = ee0[ 0] - ee2[ 0]; - k11 = ee0[-1] - ee2[-1]; - ee0[ 0] = ee0[ 0] + ee2[ 0]; - ee0[-1] = ee0[-1] + ee2[-1]; - ee2[ 0] = (k00) * A0 - (k11) * A1; - ee2[-1] = (k11) * A0 + (k00) * A1; - - k00 = ee0[-2] - ee2[-2]; - k11 = ee0[-3] - ee2[-3]; - ee0[-2] = ee0[-2] + ee2[-2]; - ee0[-3] = ee0[-3] + ee2[-3]; - ee2[-2] = (k00) * A2 - (k11) * A3; - ee2[-3] = (k11) * A2 + (k00) * A3; - - k00 = ee0[-4] - ee2[-4]; - k11 = ee0[-5] - ee2[-5]; - ee0[-4] = ee0[-4] + ee2[-4]; - ee0[-5] = ee0[-5] + ee2[-5]; - ee2[-4] = (k00) * A4 - (k11) * A5; - ee2[-5] = (k11) * A4 + (k00) * A5; - - k00 = ee0[-6] - ee2[-6]; - k11 = ee0[-7] - ee2[-7]; - ee0[-6] = ee0[-6] + ee2[-6]; - ee0[-7] = ee0[-7] + ee2[-7]; - ee2[-6] = (k00) * A6 - (k11) * A7; - ee2[-7] = (k11) * A6 + (k00) * A7; - - ee0 -= k0; - ee2 -= k0; - } -} - -static __forceinline void iter_54(float *z) -{ - float k00,k11,k22,k33; - float y0,y1,y2,y3; - - k00 = z[ 0] - z[-4]; - y0 = z[ 0] + z[-4]; - y2 = z[-2] + z[-6]; - k22 = z[-2] - z[-6]; - - z[-0] = y0 + y2; // z0 + z4 + z2 + z6 - z[-2] = y0 - y2; // z0 + z4 - z2 - z6 - - // done with y0,y2 - - k33 = z[-3] - z[-7]; - - z[-4] = k00 + k33; // z0 - z4 + z3 - z7 - z[-6] = k00 - k33; // z0 - z4 - z3 + z7 - - // done with k33 - - k11 = z[-1] - z[-5]; - y1 = z[-1] + z[-5]; - y3 = z[-3] + z[-7]; - - z[-1] = y1 + y3; // z1 + z5 + z3 + z7 - z[-3] = y1 - y3; // z1 + z5 - z3 - z7 - z[-5] = k11 - k22; // z1 - z5 + z2 - z6 - z[-7] = k11 + k22; // z1 - z5 - z2 + z6 -} - -static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n) -{ - int a_off = base_n >> 3; - float A2 = A[0+a_off]; - float *z = e + i_off; - float *base = z - 16 * n; - - while (z > base) { - float k00,k11; - float l00,l11; - - k00 = z[-0] - z[ -8]; - k11 = z[-1] - z[ -9]; - l00 = z[-2] - z[-10]; - l11 = z[-3] - z[-11]; - z[ -0] = z[-0] + z[ -8]; - z[ -1] = z[-1] + z[ -9]; - z[ -2] = z[-2] + z[-10]; - z[ -3] = z[-3] + z[-11]; - z[ -8] = k00; - z[ -9] = k11; - z[-10] = (l00+l11) * A2; - z[-11] = (l11-l00) * A2; - - k00 = z[ -4] - z[-12]; - k11 = z[ -5] - z[-13]; - l00 = z[ -6] - z[-14]; - l11 = z[ -7] - z[-15]; - z[ -4] = z[ -4] + z[-12]; - z[ -5] = z[ -5] + z[-13]; - z[ -6] = z[ -6] + z[-14]; - z[ -7] = z[ -7] + z[-15]; - z[-12] = k11; - z[-13] = -k00; - z[-14] = (l11-l00) * A2; - z[-15] = (l00+l11) * -A2; - - iter_54(z); - iter_54(z-8); - z -= 16; - } -} - -static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) -{ - int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; - int ld; - // @OPTIMIZE: reduce register pressure by using fewer variables? - int save_point = temp_alloc_save(f); - float *buf2 = (float *) temp_alloc(f, n2 * sizeof(*buf2)); - float *u=NULL,*v=NULL; - // twiddle factors - float *A = f->A[blocktype]; - - // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" - // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function. - - // kernel from paper - - - // merged: - // copy and reflect spectral data - // step 0 - - // note that it turns out that the items added together during - // this step are, in fact, being added to themselves (as reflected - // by step 0). inexplicable inefficiency! this became obvious - // once I combined the passes. - - // so there's a missing 'times 2' here (for adding X to itself). - // this propagates through linearly to the end, where the numbers - // are 1/2 too small, and need to be compensated for. - - { - float *d,*e, *AA, *e_stop; - d = &buf2[n2-2]; - AA = A; - e = &buffer[0]; - e_stop = &buffer[n2]; - while (e != e_stop) { - d[1] = (e[0] * AA[0] - e[2]*AA[1]); - d[0] = (e[0] * AA[1] + e[2]*AA[0]); - d -= 2; - AA += 2; - e += 4; - } - - e = &buffer[n2-3]; - while (d >= buf2) { - d[1] = (-e[2] * AA[0] - -e[0]*AA[1]); - d[0] = (-e[2] * AA[1] + -e[0]*AA[0]); - d -= 2; - AA += 2; - e -= 4; - } - } - - // now we use symbolic names for these, so that we can - // possibly swap their meaning as we change which operations - // are in place - - u = buffer; - v = buf2; - - // step 2 (paper output is w, now u) - // this could be in place, but the data ends up in the wrong - // place... _somebody_'s got to swap it, so this is nominated - { - float *AA = &A[n2-8]; - float *d0,*d1, *e0, *e1; - - e0 = &v[n4]; - e1 = &v[0]; - - d0 = &u[n4]; - d1 = &u[0]; - - while (AA >= A) { - float v40_20, v41_21; - - v41_21 = e0[1] - e1[1]; - v40_20 = e0[0] - e1[0]; - d0[1] = e0[1] + e1[1]; - d0[0] = e0[0] + e1[0]; - d1[1] = v41_21*AA[4] - v40_20*AA[5]; - d1[0] = v40_20*AA[4] + v41_21*AA[5]; - - v41_21 = e0[3] - e1[3]; - v40_20 = e0[2] - e1[2]; - d0[3] = e0[3] + e1[3]; - d0[2] = e0[2] + e1[2]; - d1[3] = v41_21*AA[0] - v40_20*AA[1]; - d1[2] = v40_20*AA[0] + v41_21*AA[1]; - - AA -= 8; - - d0 += 4; - d1 += 4; - e0 += 4; - e1 += 4; - } - } - - // step 3 - ld = ilog(n) - 1; // ilog is off-by-one from normal definitions - - // optimized step 3: - - // the original step3 loop can be nested r inside s or s inside r; - // it's written originally as s inside r, but this is dumb when r - // iterates many times, and s few. So I have two copies of it and - // switch between them halfway. - - // this is iteration 0 of step 3 - imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n >> 3), A); - imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n >> 3), A); - - // this is iteration 1 of step 3 - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n >> 4), A, 16); - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n >> 4), A, 16); - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n >> 4), A, 16); - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n >> 4), A, 16); - - l=2; - for (; l < (ld-3)>>1; ++l) { - int k0 = n >> (l+2), k0_2 = k0>>1; - int lim = 1 << (l+1); - int i; - for (i=0; i < lim; ++i) - imdct_step3_inner_r_loop(n >> (l+4), u, n2-1 - k0*i, -k0_2, A, 1 << (l+3)); - } - - for (; l < ld-6; ++l) { - int k0 = n >> (l+2), k1 = 1 << (l+3), k0_2 = k0>>1; - int rlim = n >> (l+6), r; - int lim = 1 << (l+1); - int i_off; - float *A0 = A; - i_off = n2-1; - for (r=rlim; r > 0; --r) { - imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0); - A0 += k1*4; - i_off -= 8; - } - } - - // iterations with count: - // ld-6,-5,-4 all interleaved together - // the big win comes from getting rid of needless flops - // due to the constants on pass 5 & 4 being all 1 and 0; - // combining them to be simultaneous to improve cache made little difference - imdct_step3_inner_s_loop_ld654(n >> 5, u, n2-1, A, n); - - // output is u - - // step 4, 5, and 6 - // cannot be in-place because of step 5 - { - uint16 *bitrev = f->bit_reverse[blocktype]; - // weirdly, I'd have thought reading sequentially and writing - // erratically would have been better than vice-versa, but in - // fact that's not what my testing showed. (That is, with - // j = bitreverse(i), do you read i and write j, or read j and write i.) - - float *d0 = &v[n4-4]; - float *d1 = &v[n2-4]; - while (d0 >= v) { - int k4; - - k4 = bitrev[0]; - d1[3] = u[k4+0]; - d1[2] = u[k4+1]; - d0[3] = u[k4+2]; - d0[2] = u[k4+3]; - - k4 = bitrev[1]; - d1[1] = u[k4+0]; - d1[0] = u[k4+1]; - d0[1] = u[k4+2]; - d0[0] = u[k4+3]; - - d0 -= 4; - d1 -= 4; - bitrev += 2; - } - } - // (paper output is u, now v) - - - // data must be in buf2 - assert(v == buf2); - - // step 7 (paper output is v, now v) - // this is now in place - { - float *C = f->C[blocktype]; - float *d, *e; - - d = v; - e = v + n2 - 4; - - while (d < e) { - float a02,a11,b0,b1,b2,b3; - - a02 = d[0] - e[2]; - a11 = d[1] + e[3]; - - b0 = C[1]*a02 + C[0]*a11; - b1 = C[1]*a11 - C[0]*a02; - - b2 = d[0] + e[ 2]; - b3 = d[1] - e[ 3]; - - d[0] = b2 + b0; - d[1] = b3 + b1; - e[2] = b2 - b0; - e[3] = b1 - b3; - - a02 = d[2] - e[0]; - a11 = d[3] + e[1]; - - b0 = C[3]*a02 + C[2]*a11; - b1 = C[3]*a11 - C[2]*a02; - - b2 = d[2] + e[ 0]; - b3 = d[3] - e[ 1]; - - d[2] = b2 + b0; - d[3] = b3 + b1; - e[0] = b2 - b0; - e[1] = b1 - b3; - - C += 4; - d += 4; - e -= 4; - } - } - - // data must be in buf2 - - - // step 8+decode (paper output is X, now buffer) - // this generates pairs of data a la 8 and pushes them directly through - // the decode kernel (pushing rather than pulling) to avoid having - // to make another pass later - - // this cannot POSSIBLY be in place, so we refer to the buffers directly - - { - float *d0,*d1,*d2,*d3; - - float *B = f->B[blocktype] + n2 - 8; - float *e = buf2 + n2 - 8; - d0 = &buffer[0]; - d1 = &buffer[n2-4]; - d2 = &buffer[n2]; - d3 = &buffer[n-4]; - while (e >= v) { - float p0,p1,p2,p3; - - p3 = e[6]*B[7] - e[7]*B[6]; - p2 = -e[6]*B[6] - e[7]*B[7]; - - d0[0] = p3; - d1[3] = - p3; - d2[0] = p2; - d3[3] = p2; - - p1 = e[4]*B[5] - e[5]*B[4]; - p0 = -e[4]*B[4] - e[5]*B[5]; - - d0[1] = p1; - d1[2] = - p1; - d2[1] = p0; - d3[2] = p0; - - p3 = e[2]*B[3] - e[3]*B[2]; - p2 = -e[2]*B[2] - e[3]*B[3]; - - d0[2] = p3; - d1[1] = - p3; - d2[2] = p2; - d3[1] = p2; - - p1 = e[0]*B[1] - e[1]*B[0]; - p0 = -e[0]*B[0] - e[1]*B[1]; - - d0[3] = p1; - d1[0] = - p1; - d2[3] = p0; - d3[0] = p0; - - B -= 8; - e -= 8; - d0 += 4; - d2 += 4; - d1 -= 4; - d3 -= 4; - } - } - - temp_free(f,buf2); - temp_alloc_restore(f,save_point); -} - -#if 0 -// this is the original version of the above code, if you want to optimize it from scratch -void inverse_mdct_naive(float *buffer, int n) -{ - float s; - float A[1 << 12], B[1 << 12], C[1 << 11]; - int i,k,k2,k4, n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; - int n3_4 = n - n4, ld; - // how can they claim this only uses N words?! - // oh, because they're only used sparsely, whoops - float u[1 << 13], X[1 << 13], v[1 << 13], w[1 << 13]; - // set up twiddle factors - - for (k=k2=0; k < n4; ++k,k2+=2) { - A[k2 ] = (float) cos(4*k*M_PI/n); - A[k2+1] = (float) -sin(4*k*M_PI/n); - B[k2 ] = (float) cos((k2+1)*M_PI/n/2); - B[k2+1] = (float) sin((k2+1)*M_PI/n/2); - } - for (k=k2=0; k < n8; ++k,k2+=2) { - C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); - C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); - } - - // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" - // Note there are bugs in that pseudocode, presumably due to them attempting - // to rename the arrays nicely rather than representing the way their actual - // implementation bounces buffers back and forth. As a result, even in the - // "some formulars corrected" version, a direct implementation fails. These - // are noted below as "paper bug". - - // copy and reflect spectral data - for (k=0; k < n2; ++k) u[k] = buffer[k]; - for ( ; k < n ; ++k) u[k] = -buffer[n - k - 1]; - // kernel from paper - // step 1 - for (k=k2=k4=0; k < n4; k+=1, k2+=2, k4+=4) { - v[n-k4-1] = (u[k4] - u[n-k4-1]) * A[k2] - (u[k4+2] - u[n-k4-3])*A[k2+1]; - v[n-k4-3] = (u[k4] - u[n-k4-1]) * A[k2+1] + (u[k4+2] - u[n-k4-3])*A[k2]; - } - // step 2 - for (k=k4=0; k < n8; k+=1, k4+=4) { - w[n2+3+k4] = v[n2+3+k4] + v[k4+3]; - w[n2+1+k4] = v[n2+1+k4] + v[k4+1]; - w[k4+3] = (v[n2+3+k4] - v[k4+3])*A[n2-4-k4] - (v[n2+1+k4]-v[k4+1])*A[n2-3-k4]; - w[k4+1] = (v[n2+1+k4] - v[k4+1])*A[n2-4-k4] + (v[n2+3+k4]-v[k4+3])*A[n2-3-k4]; - } - // step 3 - ld = ilog(n) - 1; // ilog is off-by-one from normal definitions - for (l=0; l < ld-3; ++l) { - int k0 = n >> (l+2), k1 = 1 << (l+3); - int rlim = n >> (l+4), r4, r; - int s2lim = 1 << (l+2), s2; - for (r=r4=0; r < rlim; r4+=4,++r) { - for (s2=0; s2 < s2lim; s2+=2) { - u[n-1-k0*s2-r4] = w[n-1-k0*s2-r4] + w[n-1-k0*(s2+1)-r4]; - u[n-3-k0*s2-r4] = w[n-3-k0*s2-r4] + w[n-3-k0*(s2+1)-r4]; - u[n-1-k0*(s2+1)-r4] = (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1] - - (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1+1]; - u[n-3-k0*(s2+1)-r4] = (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1] - + (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1+1]; - } - } - if (l+1 < ld-3) { - // paper bug: ping-ponging of u&w here is omitted - memcpy(w, u, sizeof(u)); - } - } - - // step 4 - for (i=0; i < n8; ++i) { - int j = bit_reverse(i) >> (32-ld+3); - assert(j < n8); - if (i == j) { - // paper bug: original code probably swapped in place; if copying, - // need to directly copy in this case - int i8 = i << 3; - v[i8+1] = u[i8+1]; - v[i8+3] = u[i8+3]; - v[i8+5] = u[i8+5]; - v[i8+7] = u[i8+7]; - } else if (i < j) { - int i8 = i << 3, j8 = j << 3; - v[j8+1] = u[i8+1], v[i8+1] = u[j8 + 1]; - v[j8+3] = u[i8+3], v[i8+3] = u[j8 + 3]; - v[j8+5] = u[i8+5], v[i8+5] = u[j8 + 5]; - v[j8+7] = u[i8+7], v[i8+7] = u[j8 + 7]; - } - } - // step 5 - for (k=0; k < n2; ++k) { - w[k] = v[k*2+1]; - } - // step 6 - for (k=k2=k4=0; k < n8; ++k, k2 += 2, k4 += 4) { - u[n-1-k2] = w[k4]; - u[n-2-k2] = w[k4+1]; - u[n3_4 - 1 - k2] = w[k4+2]; - u[n3_4 - 2 - k2] = w[k4+3]; - } - // step 7 - for (k=k2=0; k < n8; ++k, k2 += 2) { - v[n2 + k2 ] = ( u[n2 + k2] + u[n-2-k2] + C[k2+1]*(u[n2+k2]-u[n-2-k2]) + C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; - v[n-2 - k2] = ( u[n2 + k2] + u[n-2-k2] - C[k2+1]*(u[n2+k2]-u[n-2-k2]) - C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; - v[n2+1+ k2] = ( u[n2+1+k2] - u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; - v[n-1 - k2] = (-u[n2+1+k2] + u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; - } - // step 8 - for (k=k2=0; k < n4; ++k,k2 += 2) { - X[k] = v[k2+n2]*B[k2 ] + v[k2+1+n2]*B[k2+1]; - X[n2-1-k] = v[k2+n2]*B[k2+1] - v[k2+1+n2]*B[k2 ]; - } - - // decode kernel to output - // determined the following value experimentally - // (by first figuring out what made inverse_mdct_slow work); then matching that here - // (probably vorbis encoder premultiplies by n or n/2, to save it on the decoder?) - s = 0.5; // theoretically would be n4 - - // [[[ note! the s value of 0.5 is compensated for by the B[] in the current code, - // so it needs to use the "old" B values to behave correctly, or else - // set s to 1.0 ]]] - for (i=0; i < n4 ; ++i) buffer[i] = s * X[i+n4]; - for ( ; i < n3_4; ++i) buffer[i] = -s * X[n3_4 - i - 1]; - for ( ; i < n ; ++i) buffer[i] = -s * X[i - n3_4]; -} -#endif - -static float *get_window(vorb *f, int len) -{ - len <<= 1; - if (len == f->blocksize_0) return f->window[0]; - if (len == f->blocksize_1) return f->window[1]; - return NULL; -} - -#ifndef STB_VORBIS_NO_DEFER_FLOOR -typedef int16 YTYPE; -#else -typedef int YTYPE; -#endif -static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *finalY, uint8 *step2_flag) -{ - int n2 = n >> 1; - int s = map->chan[i].mux, floor; - floor = map->submap_floor[s]; - if (f->floor_types[floor] == 0) { - return error(f, VORBIS_invalid_stream); - } else { - Floor1 *g = &f->floor_config[floor].floor1; - int j,q; - int lx = 0, ly = finalY[0] * g->floor1_multiplier; - for (q=1; q < g->values; ++q) { - j = g->sorted_order[q]; - #ifndef STB_VORBIS_NO_DEFER_FLOOR - STBV_NOTUSED(step2_flag); - if (finalY[j] >= 0) - #else - if (step2_flag[j]) - #endif - { - int hy = finalY[j] * g->floor1_multiplier; - int hx = g->Xlist[j]; - if (lx != hx) - draw_line(target, lx,ly, hx,hy, n2); - CHECK(f); - lx = hx, ly = hy; - } - } - if (lx < n2) { - // optimization of: draw_line(target, lx,ly, n,ly, n2); - for (j=lx; j < n2; ++j) - LINE_OP(target[j], inverse_db_table[ly]); - CHECK(f); - } - } - return TRUE; -} - -// The meaning of "left" and "right" -// -// For a given frame: -// we compute samples from 0..n -// window_center is n/2 -// we'll window and mix the samples from left_start to left_end with data from the previous frame -// all of the samples from left_end to right_start can be output without mixing; however, -// this interval is 0-length except when transitioning between short and long frames -// all of the samples from right_start to right_end need to be mixed with the next frame, -// which we don't have, so those get saved in a buffer -// frame N's right_end-right_start, the number of samples to mix with the next frame, -// has to be the same as frame N+1's left_end-left_start (which they are by -// construction) - -static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) -{ - Mode *m; - int i, n, prev, next, window_center; - f->channel_buffer_start = f->channel_buffer_end = 0; - - retry: - if (f->eof) return FALSE; - if (!maybe_start_packet(f)) - return FALSE; - // check packet type - if (get_bits(f,1) != 0) { - if (IS_PUSH_MODE(f)) - return error(f,VORBIS_bad_packet_type); - while (EOP != get8_packet(f)); - goto retry; - } - - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - - i = get_bits(f, ilog(f->mode_count-1)); - if (i == EOP) return FALSE; - if (i >= f->mode_count) return FALSE; - *mode = i; - m = f->mode_config + i; - if (m->blockflag) { - n = f->blocksize_1; - prev = get_bits(f,1); - next = get_bits(f,1); - } else { - prev = next = 0; - n = f->blocksize_0; - } - -// WINDOWING - - window_center = n >> 1; - if (m->blockflag && !prev) { - *p_left_start = (n - f->blocksize_0) >> 2; - *p_left_end = (n + f->blocksize_0) >> 2; - } else { - *p_left_start = 0; - *p_left_end = window_center; - } - if (m->blockflag && !next) { - *p_right_start = (n*3 - f->blocksize_0) >> 2; - *p_right_end = (n*3 + f->blocksize_0) >> 2; - } else { - *p_right_start = window_center; - *p_right_end = n; - } - - return TRUE; -} - -static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, int left_end, int right_start, int right_end, int *p_left) -{ - Mapping *map; - int i,j,k,n,n2; - int zero_channel[256]; - int really_zero_channel[256]; - -// WINDOWING - - STBV_NOTUSED(left_end); - n = f->blocksize[m->blockflag]; - map = &f->mapping[m->mapping]; - -// FLOORS - n2 = n >> 1; - - CHECK(f); - - for (i=0; i < f->channels; ++i) { - int s = map->chan[i].mux, floor; - zero_channel[i] = FALSE; - floor = map->submap_floor[s]; - if (f->floor_types[floor] == 0) { - return error(f, VORBIS_invalid_stream); - } else { - Floor1 *g = &f->floor_config[floor].floor1; - if (get_bits(f, 1)) { - short *finalY; - uint8 step2_flag[256]; - static int range_list[4] = { 256, 128, 86, 64 }; - int range = range_list[g->floor1_multiplier-1]; - int offset = 2; - finalY = f->finalY[i]; - finalY[0] = get_bits(f, ilog(range)-1); - finalY[1] = get_bits(f, ilog(range)-1); - for (j=0; j < g->partitions; ++j) { - int pclass = g->partition_class_list[j]; - int cdim = g->class_dimensions[pclass]; - int cbits = g->class_subclasses[pclass]; - int csub = (1 << cbits)-1; - int cval = 0; - if (cbits) { - Codebook *c = f->codebooks + g->class_masterbooks[pclass]; - DECODE(cval,f,c); - } - for (k=0; k < cdim; ++k) { - int book = g->subclass_books[pclass][cval & csub]; - cval = cval >> cbits; - if (book >= 0) { - int temp; - Codebook *c = f->codebooks + book; - DECODE(temp,f,c); - finalY[offset++] = temp; - } else - finalY[offset++] = 0; - } - } - if (f->valid_bits == INVALID_BITS) goto error; // behavior according to spec - step2_flag[0] = step2_flag[1] = 1; - for (j=2; j < g->values; ++j) { - int low, high, pred, highroom, lowroom, room, val; - low = g->neighbors[j][0]; - high = g->neighbors[j][1]; - //neighbors(g->Xlist, j, &low, &high); - pred = predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]); - val = finalY[j]; - highroom = range - pred; - lowroom = pred; - if (highroom < lowroom) - room = highroom * 2; - else - room = lowroom * 2; - if (val) { - step2_flag[low] = step2_flag[high] = 1; - step2_flag[j] = 1; - if (val >= room) - if (highroom > lowroom) - finalY[j] = val - lowroom + pred; - else - finalY[j] = pred - val + highroom - 1; - else - if (val & 1) - finalY[j] = pred - ((val+1)>>1); - else - finalY[j] = pred + (val>>1); - } else { - step2_flag[j] = 0; - finalY[j] = pred; - } - } - -#ifdef STB_VORBIS_NO_DEFER_FLOOR - do_floor(f, map, i, n, f->floor_buffers[i], finalY, step2_flag); -#else - // defer final floor computation until _after_ residue - for (j=0; j < g->values; ++j) { - if (!step2_flag[j]) - finalY[j] = -1; - } -#endif - } else { - error: - zero_channel[i] = TRUE; - } - // So we just defer everything else to later - - // at this point we've decoded the floor into buffer - } - } - CHECK(f); - // at this point we've decoded all floors - - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - - // re-enable coupled channels if necessary - memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels); - for (i=0; i < map->coupling_steps; ++i) - if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) { - zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE; - } - - CHECK(f); -// RESIDUE DECODE - for (i=0; i < map->submaps; ++i) { - float *residue_buffers[STB_VORBIS_MAX_CHANNELS]; - int r; - uint8 do_not_decode[256]; - int ch = 0; - for (j=0; j < f->channels; ++j) { - if (map->chan[j].mux == i) { - if (zero_channel[j]) { - do_not_decode[ch] = TRUE; - residue_buffers[ch] = NULL; - } else { - do_not_decode[ch] = FALSE; - residue_buffers[ch] = f->channel_buffers[j]; - } - ++ch; - } - } - r = map->submap_residue[i]; - decode_residue(f, residue_buffers, ch, n2, r, do_not_decode); - } - - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - CHECK(f); - -// INVERSE COUPLING - for (i = map->coupling_steps-1; i >= 0; --i) { - int n2 = n >> 1; - float *m = f->channel_buffers[map->chan[i].magnitude]; - float *a = f->channel_buffers[map->chan[i].angle ]; - for (j=0; j < n2; ++j) { - float a2,m2; - if (m[j] > 0) - if (a[j] > 0) - m2 = m[j], a2 = m[j] - a[j]; - else - a2 = m[j], m2 = m[j] + a[j]; - else - if (a[j] > 0) - m2 = m[j], a2 = m[j] + a[j]; - else - a2 = m[j], m2 = m[j] - a[j]; - m[j] = m2; - a[j] = a2; - } - } - CHECK(f); - - // finish decoding the floors -#ifndef STB_VORBIS_NO_DEFER_FLOOR - for (i=0; i < f->channels; ++i) { - if (really_zero_channel[i]) { - memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); - } else { - do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL); - } - } -#else - for (i=0; i < f->channels; ++i) { - if (really_zero_channel[i]) { - memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); - } else { - for (j=0; j < n2; ++j) - f->channel_buffers[i][j] *= f->floor_buffers[i][j]; - } - } -#endif - -// INVERSE MDCT - CHECK(f); - for (i=0; i < f->channels; ++i) - inverse_mdct(f->channel_buffers[i], n, f, m->blockflag); - CHECK(f); - - // this shouldn't be necessary, unless we exited on an error - // and want to flush to get to the next packet - flush_packet(f); - - if (f->first_decode) { - // assume we start so first non-discarded sample is sample 0 - // this isn't to spec, but spec would require us to read ahead - // and decode the size of all current frames--could be done, - // but presumably it's not a commonly used feature - f->current_loc = 0u - n2; // start of first frame is positioned for discard (NB this is an intentional unsigned overflow/wrap-around) - // we might have to discard samples "from" the next frame too, - // if we're lapping a large block then a small at the start? - f->discard_samples_deferred = n - right_end; - f->current_loc_valid = TRUE; - f->first_decode = FALSE; - } else if (f->discard_samples_deferred) { - if (f->discard_samples_deferred >= right_start - left_start) { - f->discard_samples_deferred -= (right_start - left_start); - left_start = right_start; - *p_left = left_start; - } else { - left_start += f->discard_samples_deferred; - *p_left = left_start; - f->discard_samples_deferred = 0; - } - } else if (f->previous_length == 0 && f->current_loc_valid) { - // we're recovering from a seek... that means we're going to discard - // the samples from this packet even though we know our position from - // the last page header, so we need to update the position based on - // the discarded samples here - // but wait, the code below is going to add this in itself even - // on a discard, so we don't need to do it here... - } - - // check if we have ogg information about the sample # for this packet - if (f->last_seg_which == f->end_seg_with_known_loc) { - // if we have a valid current loc, and this is final: - if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { - uint32 current_end = f->known_loc_for_packet; - // then let's infer the size of the (probably) short final frame - if (current_end < f->current_loc + (right_end-left_start)) { - if (current_end < f->current_loc) { - // negative truncation, that's impossible! - *len = 0; - } else { - *len = current_end - f->current_loc; - } - *len += left_start; // this doesn't seem right, but has no ill effect on my test files - if (*len > right_end) *len = right_end; // this should never happen - f->current_loc += *len; - return TRUE; - } - } - // otherwise, just set our sample loc - // guess that the ogg granule pos refers to the _middle_ of the - // last frame? - // set f->current_loc to the position of left_start - f->current_loc = f->known_loc_for_packet - (n2-left_start); - f->current_loc_valid = TRUE; - } - if (f->current_loc_valid) - f->current_loc += (right_start - left_start); - - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - *len = right_end; // ignore samples after the window goes to 0 - CHECK(f); - - return TRUE; -} - -static int vorbis_decode_packet(vorb *f, int *len, int *p_left, int *p_right) -{ - int mode, left_end, right_end; - if (!vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0; - return vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left); -} - -static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right) -{ - int prev,i,j; - // we use right&left (the start of the right- and left-window sin()-regions) - // to determine how much to return, rather than inferring from the rules - // (same result, clearer code); 'left' indicates where our sin() window - // starts, therefore where the previous window's right edge starts, and - // therefore where to start mixing from the previous buffer. 'right' - // indicates where our sin() ending-window starts, therefore that's where - // we start saving, and where our returned-data ends. - - // mixin from previous window - if (f->previous_length) { - int i,j, n = f->previous_length; - float *w = get_window(f, n); - if (w == NULL) return 0; - for (i=0; i < f->channels; ++i) { - for (j=0; j < n; ++j) - f->channel_buffers[i][left+j] = - f->channel_buffers[i][left+j]*w[ j] + - f->previous_window[i][ j]*w[n-1-j]; - } - } - - prev = f->previous_length; - - // last half of this data becomes previous window - f->previous_length = len - right; - - // @OPTIMIZE: could avoid this copy by double-buffering the - // output (flipping previous_window with channel_buffers), but - // then previous_window would have to be 2x as large, and - // channel_buffers couldn't be temp mem (although they're NOT - // currently temp mem, they could be (unless we want to level - // performance by spreading out the computation)) - for (i=0; i < f->channels; ++i) - for (j=0; right+j < len; ++j) - f->previous_window[i][j] = f->channel_buffers[i][right+j]; - - if (!prev) - // there was no previous packet, so this data isn't valid... - // this isn't entirely true, only the would-have-overlapped data - // isn't valid, but this seems to be what the spec requires - return 0; - - // truncate a short frame - if (len < right) right = len; - - f->samples_output += right-left; - - return right - left; -} - -static int vorbis_pump_first_frame(stb_vorbis *f) -{ - int len, right, left, res; - res = vorbis_decode_packet(f, &len, &left, &right); - if (res) - vorbis_finish_frame(f, len, left, right); - return res; -} - -#ifndef STB_VORBIS_NO_PUSHDATA_API -static int is_whole_packet_present(stb_vorbis *f) -{ - // make sure that we have the packet available before continuing... - // this requires a full ogg parse, but we know we can fetch from f->stream - - // instead of coding this out explicitly, we could save the current read state, - // read the next packet with get8() until end-of-packet, check f->eof, then - // reset the state? but that would be slower, esp. since we'd have over 256 bytes - // of state to restore (primarily the page segment table) - - int s = f->next_seg, first = TRUE; - uint8 *p = f->stream; - - if (s != -1) { // if we're not starting the packet with a 'continue on next page' flag - for (; s < f->segment_count; ++s) { - p += f->segments[s]; - if (f->segments[s] < 255) // stop at first short segment - break; - } - // either this continues, or it ends it... - if (s == f->segment_count) - s = -1; // set 'crosses page' flag - if (p > f->stream_end) return error(f, VORBIS_need_more_data); - first = FALSE; - } - for (; s == -1;) { - uint8 *q; - int n; - - // check that we have the page header ready - if (p + 26 >= f->stream_end) return error(f, VORBIS_need_more_data); - // validate the page - if (memcmp(p, ogg_page_header, 4)) return error(f, VORBIS_invalid_stream); - if (p[4] != 0) return error(f, VORBIS_invalid_stream); - if (first) { // the first segment must NOT have 'continued_packet', later ones MUST - if (f->previous_length) - if ((p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); - // if no previous length, we're resynching, so we can come in on a continued-packet, - // which we'll just drop - } else { - if (!(p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); - } - n = p[26]; // segment counts - q = p+27; // q points to segment table - p = q + n; // advance past header - // make sure we've read the segment table - if (p > f->stream_end) return error(f, VORBIS_need_more_data); - for (s=0; s < n; ++s) { - p += q[s]; - if (q[s] < 255) - break; - } - if (s == n) - s = -1; // set 'crosses page' flag - if (p > f->stream_end) return error(f, VORBIS_need_more_data); - first = FALSE; - } - return TRUE; -} -#endif // !STB_VORBIS_NO_PUSHDATA_API - -static int start_decoder(vorb *f) -{ - uint8 header[6], x,y; - int len,i,j,k, max_submaps = 0; - int longest_floorlist=0; - - // first page, first packet - f->first_decode = TRUE; - - if (!start_page(f)) return FALSE; - // validate page flag - if (!(f->page_flag & PAGEFLAG_first_page)) return error(f, VORBIS_invalid_first_page); - if (f->page_flag & PAGEFLAG_last_page) return error(f, VORBIS_invalid_first_page); - if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page); - // check for expected packet length - if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page); - if (f->segments[0] != 30) { - // check for the Ogg skeleton fishead identifying header to refine our error - if (f->segments[0] == 64 && - getn(f, header, 6) && - header[0] == 'f' && - header[1] == 'i' && - header[2] == 's' && - header[3] == 'h' && - header[4] == 'e' && - header[5] == 'a' && - get8(f) == 'd' && - get8(f) == '\0') return error(f, VORBIS_ogg_skeleton_not_supported); - else - return error(f, VORBIS_invalid_first_page); - } - - // read packet - // check packet header - if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page); - if (!getn(f, header, 6)) return error(f, VORBIS_unexpected_eof); - if (!vorbis_validate(header)) return error(f, VORBIS_invalid_first_page); - // vorbis_version - if (get32(f) != 0) return error(f, VORBIS_invalid_first_page); - f->channels = get8(f); if (!f->channels) return error(f, VORBIS_invalid_first_page); - if (f->channels > STB_VORBIS_MAX_CHANNELS) return error(f, VORBIS_too_many_channels); - f->sample_rate = get32(f); if (!f->sample_rate) return error(f, VORBIS_invalid_first_page); - get32(f); // bitrate_maximum - get32(f); // bitrate_nominal - get32(f); // bitrate_minimum - x = get8(f); - { - int log0,log1; - log0 = x & 15; - log1 = x >> 4; - f->blocksize_0 = 1 << log0; - f->blocksize_1 = 1 << log1; - if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup); - if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup); - if (log0 > log1) return error(f, VORBIS_invalid_setup); - } - - // framing_flag - x = get8(f); - if (!(x & 1)) return error(f, VORBIS_invalid_first_page); - - // second packet! - if (!start_page(f)) return FALSE; - - if (!start_packet(f)) return FALSE; - - if (!next_segment(f)) return FALSE; - - if (get8_packet(f) != VORBIS_packet_comment) return error(f, VORBIS_invalid_setup); - for (i=0; i < 6; ++i) header[i] = get8_packet(f); - if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); - //file vendor - len = get32_packet(f); - f->vendor = (char*)setup_malloc(f, sizeof(char) * (len+1)); - if (f->vendor == NULL) return error(f, VORBIS_outofmem); - for(i=0; i < len; ++i) { - f->vendor[i] = get8_packet(f); - } - f->vendor[len] = (char)'\0'; - //user comments - f->comment_list_length = get32_packet(f); - f->comment_list = NULL; - if (f->comment_list_length > 0) - { - f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); - if (f->comment_list == NULL) return error(f, VORBIS_outofmem); - } - - for(i=0; i < f->comment_list_length; ++i) { - len = get32_packet(f); - f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1)); - if (f->comment_list[i] == NULL) return error(f, VORBIS_outofmem); - - for(j=0; j < len; ++j) { - f->comment_list[i][j] = get8_packet(f); - } - f->comment_list[i][len] = (char)'\0'; - } - - // framing_flag - x = get8_packet(f); - if (!(x & 1)) return error(f, VORBIS_invalid_setup); - - - skip(f, f->bytes_in_seg); - f->bytes_in_seg = 0; - - do { - len = next_segment(f); - skip(f, len); - f->bytes_in_seg = 0; - } while (len); - - // third packet! - if (!start_packet(f)) return FALSE; - - #ifndef STB_VORBIS_NO_PUSHDATA_API - if (IS_PUSH_MODE(f)) { - if (!is_whole_packet_present(f)) { - // convert error in ogg header to write type - if (f->error == VORBIS_invalid_stream) - f->error = VORBIS_invalid_setup; - return FALSE; - } - } - #endif - - crc32_init(); // always init it, to avoid multithread race conditions - - if (get8_packet(f) != VORBIS_packet_setup) return error(f, VORBIS_invalid_setup); - for (i=0; i < 6; ++i) header[i] = get8_packet(f); - if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); - - // codebooks - - f->codebook_count = get_bits(f,8) + 1; - f->codebooks = (Codebook *) setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count); - if (f->codebooks == NULL) return error(f, VORBIS_outofmem); - memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count); - for (i=0; i < f->codebook_count; ++i) { - uint32 *values; - int ordered, sorted_count; - int total=0; - uint8 *lengths; - Codebook *c = f->codebooks+i; - CHECK(f); - x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup); - x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup); - x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup); - x = get_bits(f, 8); - c->dimensions = (get_bits(f, 8)<<8) + x; - x = get_bits(f, 8); - y = get_bits(f, 8); - c->entries = (get_bits(f, 8)<<16) + (y<<8) + x; - ordered = get_bits(f,1); - c->sparse = ordered ? 0 : get_bits(f,1); - - if (c->dimensions == 0 && c->entries != 0) return error(f, VORBIS_invalid_setup); - - if (c->sparse) - lengths = (uint8 *) setup_temp_malloc(f, c->entries); - else - lengths = c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); - - if (!lengths) return error(f, VORBIS_outofmem); - - if (ordered) { - int current_entry = 0; - int current_length = get_bits(f,5) + 1; - while (current_entry < c->entries) { - int limit = c->entries - current_entry; - int n = get_bits(f, ilog(limit)); - if (current_length >= 32) return error(f, VORBIS_invalid_setup); - if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); } - memset(lengths + current_entry, current_length, n); - current_entry += n; - ++current_length; - } - } else { - for (j=0; j < c->entries; ++j) { - int present = c->sparse ? get_bits(f,1) : 1; - if (present) { - lengths[j] = get_bits(f, 5) + 1; - ++total; - if (lengths[j] == 32) - return error(f, VORBIS_invalid_setup); - } else { - lengths[j] = NO_CODE; - } - } - } - - if (c->sparse && total >= c->entries >> 2) { - // convert sparse items to non-sparse! - if (c->entries > (int) f->setup_temp_memory_required) - f->setup_temp_memory_required = c->entries; - - c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); - if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem); - memcpy(c->codeword_lengths, lengths, c->entries); - setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs! - lengths = c->codeword_lengths; - c->sparse = 0; - } - - // compute the size of the sorted tables - if (c->sparse) { - sorted_count = total; - } else { - sorted_count = 0; - #ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH - for (j=0; j < c->entries; ++j) - if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE) - ++sorted_count; - #endif - } - - c->sorted_entries = sorted_count; - values = NULL; - - CHECK(f); - if (!c->sparse) { - c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries); - if (!c->codewords) return error(f, VORBIS_outofmem); - } else { - unsigned int size; - if (c->sorted_entries) { - c->codeword_lengths = (uint8 *) setup_malloc(f, c->sorted_entries); - if (!c->codeword_lengths) return error(f, VORBIS_outofmem); - c->codewords = (uint32 *) setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries); - if (!c->codewords) return error(f, VORBIS_outofmem); - values = (uint32 *) setup_temp_malloc(f, sizeof(*values) * c->sorted_entries); - if (!values) return error(f, VORBIS_outofmem); - } - size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries; - if (size > f->setup_temp_memory_required) - f->setup_temp_memory_required = size; - } - - if (!compute_codewords(c, lengths, c->entries, values)) { - if (c->sparse) setup_temp_free(f, values, 0); - return error(f, VORBIS_invalid_setup); - } - - if (c->sorted_entries) { - // allocate an extra slot for sentinels - c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1)); - if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem); - // allocate an extra slot at the front so that c->sorted_values[-1] is defined - // so that we can catch that case without an extra if - c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1)); - if (c->sorted_values == NULL) return error(f, VORBIS_outofmem); - ++c->sorted_values; - c->sorted_values[-1] = -1; - compute_sorted_huffman(c, lengths, values); - } - - if (c->sparse) { - setup_temp_free(f, values, sizeof(*values)*c->sorted_entries); - setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries); - setup_temp_free(f, lengths, c->entries); - c->codewords = NULL; - } - - compute_accelerated_huffman(c); - - CHECK(f); - c->lookup_type = get_bits(f, 4); - if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup); - if (c->lookup_type > 0) { - uint16 *mults; - c->minimum_value = float32_unpack(get_bits(f, 32)); - c->delta_value = float32_unpack(get_bits(f, 32)); - c->value_bits = get_bits(f, 4)+1; - c->sequence_p = get_bits(f,1); - if (c->lookup_type == 1) { - int values = lookup1_values(c->entries, c->dimensions); - if (values < 0) return error(f, VORBIS_invalid_setup); - c->lookup_values = (uint32) values; - } else { - c->lookup_values = c->entries * c->dimensions; - } - if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup); - mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values); - if (mults == NULL) return error(f, VORBIS_outofmem); - for (j=0; j < (int) c->lookup_values; ++j) { - int q = get_bits(f, c->value_bits); - if (q == EOP) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); } - mults[j] = q; - } - -#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (c->lookup_type == 1) { - int len, sparse = c->sparse; - float last=0; - // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop - if (sparse) { - if (c->sorted_entries == 0) goto skip; - c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions); - } else - c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions); - if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } - len = sparse ? c->sorted_entries : c->entries; - for (j=0; j < len; ++j) { - unsigned int z = sparse ? c->sorted_values[j] : j; - unsigned int div=1; - for (k=0; k < c->dimensions; ++k) { - int off = (z / div) % c->lookup_values; - float val = mults[off]*c->delta_value + c->minimum_value + last; - c->multiplicands[j*c->dimensions + k] = val; - if (c->sequence_p) - last = val; - if (k+1 < c->dimensions) { - if (div > UINT_MAX / (unsigned int) c->lookup_values) { - setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); - return error(f, VORBIS_invalid_setup); - } - div *= c->lookup_values; - } - } - } - c->lookup_type = 2; - } - else -#endif - { - float last=0; - CHECK(f); - c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); - if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } - for (j=0; j < (int) c->lookup_values; ++j) { - float val = mults[j] * c->delta_value + c->minimum_value + last; - c->multiplicands[j] = val; - if (c->sequence_p) - last = val; - } - } -#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - skip:; -#endif - setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values); - - CHECK(f); - } - CHECK(f); - } - - // time domain transfers (notused) - - x = get_bits(f, 6) + 1; - for (i=0; i < x; ++i) { - uint32 z = get_bits(f, 16); - if (z != 0) return error(f, VORBIS_invalid_setup); - } - - // Floors - f->floor_count = get_bits(f, 6)+1; - f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config)); - if (f->floor_config == NULL) return error(f, VORBIS_outofmem); - for (i=0; i < f->floor_count; ++i) { - f->floor_types[i] = get_bits(f, 16); - if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup); - if (f->floor_types[i] == 0) { - Floor0 *g = &f->floor_config[i].floor0; - g->order = get_bits(f,8); - g->rate = get_bits(f,16); - g->bark_map_size = get_bits(f,16); - g->amplitude_bits = get_bits(f,6); - g->amplitude_offset = get_bits(f,8); - g->number_of_books = get_bits(f,4) + 1; - for (j=0; j < g->number_of_books; ++j) - g->book_list[j] = get_bits(f,8); - return error(f, VORBIS_feature_not_supported); - } else { - stbv__floor_ordering p[31*8+2]; - Floor1 *g = &f->floor_config[i].floor1; - int max_class = -1; - g->partitions = get_bits(f, 5); - for (j=0; j < g->partitions; ++j) { - g->partition_class_list[j] = get_bits(f, 4); - if (g->partition_class_list[j] > max_class) - max_class = g->partition_class_list[j]; - } - for (j=0; j <= max_class; ++j) { - g->class_dimensions[j] = get_bits(f, 3)+1; - g->class_subclasses[j] = get_bits(f, 2); - if (g->class_subclasses[j]) { - g->class_masterbooks[j] = get_bits(f, 8); - if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup); - } - for (k=0; k < 1 << g->class_subclasses[j]; ++k) { - g->subclass_books[j][k] = (int16)get_bits(f,8)-1; - if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); - } - } - g->floor1_multiplier = get_bits(f,2)+1; - g->rangebits = get_bits(f,4); - g->Xlist[0] = 0; - g->Xlist[1] = 1 << g->rangebits; - g->values = 2; - for (j=0; j < g->partitions; ++j) { - int c = g->partition_class_list[j]; - for (k=0; k < g->class_dimensions[c]; ++k) { - g->Xlist[g->values] = get_bits(f, g->rangebits); - ++g->values; - } - } - // precompute the sorting - for (j=0; j < g->values; ++j) { - p[j].x = g->Xlist[j]; - p[j].id = j; - } - qsort(p, g->values, sizeof(p[0]), point_compare); - for (j=0; j < g->values-1; ++j) - if (p[j].x == p[j+1].x) - return error(f, VORBIS_invalid_setup); - for (j=0; j < g->values; ++j) - g->sorted_order[j] = (uint8) p[j].id; - // precompute the neighbors - for (j=2; j < g->values; ++j) { - int low = 0,hi = 0; - neighbors(g->Xlist, j, &low,&hi); - g->neighbors[j][0] = low; - g->neighbors[j][1] = hi; - } - - if (g->values > longest_floorlist) - longest_floorlist = g->values; - } - } - - // Residue - f->residue_count = get_bits(f, 6)+1; - f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(f->residue_config[0])); - if (f->residue_config == NULL) return error(f, VORBIS_outofmem); - memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0])); - for (i=0; i < f->residue_count; ++i) { - uint8 residue_cascade[64]; - Residue *r = f->residue_config+i; - f->residue_types[i] = get_bits(f, 16); - if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup); - r->begin = get_bits(f, 24); - r->end = get_bits(f, 24); - if (r->end < r->begin) return error(f, VORBIS_invalid_setup); - r->part_size = get_bits(f,24)+1; - r->classifications = get_bits(f,6)+1; - r->classbook = get_bits(f,8); - if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup); - for (j=0; j < r->classifications; ++j) { - uint8 high_bits=0; - uint8 low_bits=get_bits(f,3); - if (get_bits(f,1)) - high_bits = get_bits(f,5); - residue_cascade[j] = high_bits*8 + low_bits; - } - r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications); - if (r->residue_books == NULL) return error(f, VORBIS_outofmem); - for (j=0; j < r->classifications; ++j) { - for (k=0; k < 8; ++k) { - if (residue_cascade[j] & (1 << k)) { - r->residue_books[j][k] = get_bits(f, 8); - if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); - } else { - r->residue_books[j][k] = -1; - } - } - } - // precompute the classifications[] array to avoid inner-loop mod/divide - // call it 'classdata' since we already have r->classifications - r->classdata = (uint8 **) setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); - if (!r->classdata) return error(f, VORBIS_outofmem); - memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); - for (j=0; j < f->codebooks[r->classbook].entries; ++j) { - int classwords = f->codebooks[r->classbook].dimensions; - int temp = j; - r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords); - if (r->classdata[j] == NULL) return error(f, VORBIS_outofmem); - for (k=classwords-1; k >= 0; --k) { - r->classdata[j][k] = temp % r->classifications; - temp /= r->classifications; - } - } - } - - f->mapping_count = get_bits(f,6)+1; - f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping)); - if (f->mapping == NULL) return error(f, VORBIS_outofmem); - memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping)); - for (i=0; i < f->mapping_count; ++i) { - Mapping *m = f->mapping + i; - int mapping_type = get_bits(f,16); - if (mapping_type != 0) return error(f, VORBIS_invalid_setup); - m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan)); - if (m->chan == NULL) return error(f, VORBIS_outofmem); - if (get_bits(f,1)) - m->submaps = get_bits(f,4)+1; - else - m->submaps = 1; - if (m->submaps > max_submaps) - max_submaps = m->submaps; - if (get_bits(f,1)) { - m->coupling_steps = get_bits(f,8)+1; - if (m->coupling_steps > f->channels) return error(f, VORBIS_invalid_setup); - for (k=0; k < m->coupling_steps; ++k) { - m->chan[k].magnitude = get_bits(f, ilog(f->channels-1)); - m->chan[k].angle = get_bits(f, ilog(f->channels-1)); - if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup); - if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup); - if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup); - } - } else - m->coupling_steps = 0; - - // reserved field - if (get_bits(f,2)) return error(f, VORBIS_invalid_setup); - if (m->submaps > 1) { - for (j=0; j < f->channels; ++j) { - m->chan[j].mux = get_bits(f, 4); - if (m->chan[j].mux >= m->submaps) return error(f, VORBIS_invalid_setup); - } - } else - // @SPECIFICATION: this case is missing from the spec - for (j=0; j < f->channels; ++j) - m->chan[j].mux = 0; - - for (j=0; j < m->submaps; ++j) { - get_bits(f,8); // discard - m->submap_floor[j] = get_bits(f,8); - m->submap_residue[j] = get_bits(f,8); - if (m->submap_floor[j] >= f->floor_count) return error(f, VORBIS_invalid_setup); - if (m->submap_residue[j] >= f->residue_count) return error(f, VORBIS_invalid_setup); - } - } - - // Modes - f->mode_count = get_bits(f, 6)+1; - for (i=0; i < f->mode_count; ++i) { - Mode *m = f->mode_config+i; - m->blockflag = get_bits(f,1); - m->windowtype = get_bits(f,16); - m->transformtype = get_bits(f,16); - m->mapping = get_bits(f,8); - if (m->windowtype != 0) return error(f, VORBIS_invalid_setup); - if (m->transformtype != 0) return error(f, VORBIS_invalid_setup); - if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup); - } - - flush_packet(f); - - f->previous_length = 0; - - for (i=0; i < f->channels; ++i) { - f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1); - f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); - f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist); - if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem); - memset(f->channel_buffers[i], 0, sizeof(float) * f->blocksize_1); - #ifdef STB_VORBIS_NO_DEFER_FLOOR - f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); - if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem); - #endif - } - - if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE; - if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE; - f->blocksize[0] = f->blocksize_0; - f->blocksize[1] = f->blocksize_1; - -#ifdef STB_VORBIS_DIVIDE_TABLE - if (integer_divide_table[1][1]==0) - for (i=0; i < DIVTAB_NUMER; ++i) - for (j=1; j < DIVTAB_DENOM; ++j) - integer_divide_table[i][j] = i / j; -#endif - - // compute how much temporary memory is needed - - // 1. - { - uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1); - uint32 classify_mem; - int i,max_part_read=0; - for (i=0; i < f->residue_count; ++i) { - Residue *r = f->residue_config + i; - unsigned int actual_size = f->blocksize_1 / 2; - unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size; - unsigned int limit_r_end = r->end < actual_size ? r->end : actual_size; - int n_read = limit_r_end - limit_r_begin; - int part_read = n_read / r->part_size; - if (part_read > max_part_read) - max_part_read = part_read; - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8 *)); - #else - classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); - #endif - - // maximum reasonable partition size is f->blocksize_1 - - f->temp_memory_required = classify_mem; - if (imdct_mem > f->temp_memory_required) - f->temp_memory_required = imdct_mem; - } - - - if (f->alloc.alloc_buffer) { - assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes); - // check if there's enough temp memory so we don't error later - if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset) - return error(f, VORBIS_outofmem); - } - - // @TODO: stb_vorbis_seek_start expects first_audio_page_offset to point to a page - // without PAGEFLAG_continued_packet, so this either points to the first page, or - // the page after the end of the headers. It might be cleaner to point to a page - // in the middle of the headers, when that's the page where the first audio packet - // starts, but we'd have to also correctly skip the end of any continued packet in - // stb_vorbis_seek_start. - if (f->next_seg == -1) { - f->first_audio_page_offset = stb_vorbis_get_file_offset(f); - } else { - f->first_audio_page_offset = 0; - } - - return TRUE; -} - -static void vorbis_deinit(stb_vorbis *p) -{ - int i,j; - - setup_free(p, p->vendor); - for (i=0; i < p->comment_list_length; ++i) { - setup_free(p, p->comment_list[i]); - } - setup_free(p, p->comment_list); - - if (p->residue_config) { - for (i=0; i < p->residue_count; ++i) { - Residue *r = p->residue_config+i; - if (r->classdata) { - for (j=0; j < p->codebooks[r->classbook].entries; ++j) - setup_free(p, r->classdata[j]); - setup_free(p, r->classdata); - } - setup_free(p, r->residue_books); - } - } - - if (p->codebooks) { - CHECK(p); - for (i=0; i < p->codebook_count; ++i) { - Codebook *c = p->codebooks + i; - setup_free(p, c->codeword_lengths); - setup_free(p, c->multiplicands); - setup_free(p, c->codewords); - setup_free(p, c->sorted_codewords); - // c->sorted_values[-1] is the first entry in the array - setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL); - } - setup_free(p, p->codebooks); - } - setup_free(p, p->floor_config); - setup_free(p, p->residue_config); - if (p->mapping) { - for (i=0; i < p->mapping_count; ++i) - setup_free(p, p->mapping[i].chan); - setup_free(p, p->mapping); - } - CHECK(p); - for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) { - setup_free(p, p->channel_buffers[i]); - setup_free(p, p->previous_window[i]); - #ifdef STB_VORBIS_NO_DEFER_FLOOR - setup_free(p, p->floor_buffers[i]); - #endif - setup_free(p, p->finalY[i]); - } - for (i=0; i < 2; ++i) { - setup_free(p, p->A[i]); - setup_free(p, p->B[i]); - setup_free(p, p->C[i]); - setup_free(p, p->window[i]); - setup_free(p, p->bit_reverse[i]); - } - #ifndef STB_VORBIS_NO_STDIO - if (p->close_on_free) fclose(p->f); - #endif -} - -void stb_vorbis_close(stb_vorbis *p) -{ - if (p == NULL) return; - vorbis_deinit(p); - setup_free(p,p); -} - -static void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z) -{ - memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start - if (z) { - p->alloc = *z; - p->alloc.alloc_buffer_length_in_bytes &= ~7; - p->temp_offset = p->alloc.alloc_buffer_length_in_bytes; - } - p->eof = 0; - p->error = VORBIS__no_error; - p->stream = NULL; - p->codebooks = NULL; - p->page_crc_tests = -1; - #ifndef STB_VORBIS_NO_STDIO - p->close_on_free = FALSE; - p->f = NULL; - #endif -} - -int stb_vorbis_get_sample_offset(stb_vorbis *f) -{ - if (f->current_loc_valid) - return f->current_loc; - else - return -1; -} - -stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f) -{ - stb_vorbis_info d; - d.channels = f->channels; - d.sample_rate = f->sample_rate; - d.setup_memory_required = f->setup_memory_required; - d.setup_temp_memory_required = f->setup_temp_memory_required; - d.temp_memory_required = f->temp_memory_required; - d.max_frame_size = f->blocksize_1 >> 1; - return d; -} - -stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f) -{ - stb_vorbis_comment d; - d.vendor = f->vendor; - d.comment_list_length = f->comment_list_length; - d.comment_list = f->comment_list; - return d; -} - -int stb_vorbis_get_error(stb_vorbis *f) -{ - int e = f->error; - f->error = VORBIS__no_error; - return e; -} - -static stb_vorbis * vorbis_alloc(stb_vorbis *f) -{ - stb_vorbis *p = (stb_vorbis *) setup_malloc(f, sizeof(*p)); - return p; -} - -#ifndef STB_VORBIS_NO_PUSHDATA_API - -void stb_vorbis_flush_pushdata(stb_vorbis *f) -{ - f->previous_length = 0; - f->page_crc_tests = 0; - f->discard_samples_deferred = 0; - f->current_loc_valid = FALSE; - f->first_decode = FALSE; - f->samples_output = 0; - f->channel_buffer_start = 0; - f->channel_buffer_end = 0; -} - -static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len) -{ - int i,n; - for (i=0; i < f->page_crc_tests; ++i) - f->scan[i].bytes_done = 0; - - // if we have room for more scans, search for them first, because - // they may cause us to stop early if their header is incomplete - if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) { - if (data_len < 4) return 0; - data_len -= 3; // need to look for 4-byte sequence, so don't miss - // one that straddles a boundary - for (i=0; i < data_len; ++i) { - if (data[i] == 0x4f) { - if (0==memcmp(data+i, ogg_page_header, 4)) { - int j,len; - uint32 crc; - // make sure we have the whole page header - if (i+26 >= data_len || i+27+data[i+26] >= data_len) { - // only read up to this page start, so hopefully we'll - // have the whole page header start next time - data_len = i; - break; - } - // ok, we have it all; compute the length of the page - len = 27 + data[i+26]; - for (j=0; j < data[i+26]; ++j) - len += data[i+27+j]; - // scan everything up to the embedded crc (which we must 0) - crc = 0; - for (j=0; j < 22; ++j) - crc = crc32_update(crc, data[i+j]); - // now process 4 0-bytes - for ( ; j < 26; ++j) - crc = crc32_update(crc, 0); - // len is the total number of bytes we need to scan - n = f->page_crc_tests++; - f->scan[n].bytes_left = len-j; - f->scan[n].crc_so_far = crc; - f->scan[n].goal_crc = data[i+22] + (data[i+23] << 8) + (data[i+24]<<16) + (data[i+25]<<24); - // if the last frame on a page is continued to the next, then - // we can't recover the sample_loc immediately - if (data[i+27+data[i+26]-1] == 255) - f->scan[n].sample_loc = ~0; - else - f->scan[n].sample_loc = data[i+6] + (data[i+7] << 8) + (data[i+ 8]<<16) + (data[i+ 9]<<24); - f->scan[n].bytes_done = i+j; - if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT) - break; - // keep going if we still have room for more - } - } - } - } - - for (i=0; i < f->page_crc_tests;) { - uint32 crc; - int j; - int n = f->scan[i].bytes_done; - int m = f->scan[i].bytes_left; - if (m > data_len - n) m = data_len - n; - // m is the bytes to scan in the current chunk - crc = f->scan[i].crc_so_far; - for (j=0; j < m; ++j) - crc = crc32_update(crc, data[n+j]); - f->scan[i].bytes_left -= m; - f->scan[i].crc_so_far = crc; - if (f->scan[i].bytes_left == 0) { - // does it match? - if (f->scan[i].crc_so_far == f->scan[i].goal_crc) { - // Houston, we have page - data_len = n+m; // consumption amount is wherever that scan ended - f->page_crc_tests = -1; // drop out of page scan mode - f->previous_length = 0; // decode-but-don't-output one frame - f->next_seg = -1; // start a new page - f->current_loc = f->scan[i].sample_loc; // set the current sample location - // to the amount we'd have decoded had we decoded this page - f->current_loc_valid = f->current_loc != ~0U; - return data_len; - } - // delete entry - f->scan[i] = f->scan[--f->page_crc_tests]; - } else { - ++i; - } - } - - return data_len; -} - -// return value: number of bytes we used -int stb_vorbis_decode_frame_pushdata( - stb_vorbis *f, // the file we're decoding - const uint8 *data, int data_len, // the memory available for decoding - int *channels, // place to write number of float * buffers - float ***output, // place to write float ** array of float * buffers - int *samples // place to write number of output samples - ) -{ - int i; - int len,right,left; - - if (!IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - - if (f->page_crc_tests >= 0) { - *samples = 0; - return vorbis_search_for_page_pushdata(f, (uint8 *) data, data_len); - } - - f->stream = (uint8 *) data; - f->stream_end = (uint8 *) data + data_len; - f->error = VORBIS__no_error; - - // check that we have the entire packet in memory - if (!is_whole_packet_present(f)) { - *samples = 0; - return 0; - } - - if (!vorbis_decode_packet(f, &len, &left, &right)) { - // save the actual error we encountered - enum STBVorbisError error = f->error; - if (error == VORBIS_bad_packet_type) { - // flush and resynch - f->error = VORBIS__no_error; - while (get8_packet(f) != EOP) - if (f->eof) break; - *samples = 0; - return (int) (f->stream - data); - } - if (error == VORBIS_continued_packet_flag_invalid) { - if (f->previous_length == 0) { - // we may be resynching, in which case it's ok to hit one - // of these; just discard the packet - f->error = VORBIS__no_error; - while (get8_packet(f) != EOP) - if (f->eof) break; - *samples = 0; - return (int) (f->stream - data); - } - } - // if we get an error while parsing, what to do? - // well, it DEFINITELY won't work to continue from where we are! - stb_vorbis_flush_pushdata(f); - // restore the error that actually made us bail - f->error = error; - *samples = 0; - return 1; - } - - // success! - len = vorbis_finish_frame(f, len, left, right); - for (i=0; i < f->channels; ++i) - f->outputs[i] = f->channel_buffers[i] + left; - - if (channels) *channels = f->channels; - *samples = len; - *output = f->outputs; - return (int) (f->stream - data); -} - -stb_vorbis *stb_vorbis_open_pushdata( - const unsigned char *data, int data_len, // the memory available for decoding - int *data_used, // only defined if result is not NULL - int *error, const stb_vorbis_alloc *alloc) -{ - stb_vorbis *f, p; - vorbis_init(&p, alloc); - p.stream = (uint8 *) data; - p.stream_end = (uint8 *) data + data_len; - p.push_mode = TRUE; - if (!start_decoder(&p)) { - if (p.eof) - *error = VORBIS_need_more_data; - else - *error = p.error; - vorbis_deinit(&p); - return NULL; - } - f = vorbis_alloc(&p); - if (f) { - *f = p; - *data_used = (int) (f->stream - data); - *error = 0; - return f; - } else { - vorbis_deinit(&p); - return NULL; - } -} -#endif // STB_VORBIS_NO_PUSHDATA_API - -unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) -{ - #ifndef STB_VORBIS_NO_PUSHDATA_API - if (f->push_mode) return 0; - #endif - if (USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start); - #ifndef STB_VORBIS_NO_STDIO - return (unsigned int) (ftell(f->f) - f->f_start); - #endif -} - -#ifndef STB_VORBIS_NO_PULLDATA_API -// -// DATA-PULLING API -// - -static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) -{ - for(;;) { - int n; - if (f->eof) return 0; - n = get8(f); - if (n == 0x4f) { // page header candidate - unsigned int retry_loc = stb_vorbis_get_file_offset(f); - int i; - // check if we're off the end of a file_section stream - if (retry_loc - 25 > f->stream_len) - return 0; - // check the rest of the header - for (i=1; i < 4; ++i) - if (get8(f) != ogg_page_header[i]) - break; - if (f->eof) return 0; - if (i == 4) { - uint8 header[27]; - uint32 i, crc, goal, len; - for (i=0; i < 4; ++i) - header[i] = ogg_page_header[i]; - for (; i < 27; ++i) - header[i] = get8(f); - if (f->eof) return 0; - if (header[4] != 0) goto invalid; - goal = header[22] + (header[23] << 8) + (header[24]<<16) + ((uint32)header[25]<<24); - for (i=22; i < 26; ++i) - header[i] = 0; - crc = 0; - for (i=0; i < 27; ++i) - crc = crc32_update(crc, header[i]); - len = 0; - for (i=0; i < header[26]; ++i) { - int s = get8(f); - crc = crc32_update(crc, s); - len += s; - } - if (len && f->eof) return 0; - for (i=0; i < len; ++i) - crc = crc32_update(crc, get8(f)); - // finished parsing probable page - if (crc == goal) { - // we could now check that it's either got the last - // page flag set, OR it's followed by the capture - // pattern, but I guess TECHNICALLY you could have - // a file with garbage between each ogg page and recover - // from it automatically? So even though that paranoia - // might decrease the chance of an invalid decode by - // another 2^32, not worth it since it would hose those - // invalid-but-useful files? - if (end) - *end = stb_vorbis_get_file_offset(f); - if (last) { - if (header[5] & 0x04) - *last = 1; - else - *last = 0; - } - set_file_offset(f, retry_loc-1); - return 1; - } - } - invalid: - // not a valid page, so rewind and look for next one - set_file_offset(f, retry_loc); - } - } -} - - -#define SAMPLE_unknown 0xffffffff - -// seeking is implemented with a binary search, which narrows down the range to -// 64K, before using a linear search (because finding the synchronization -// pattern can be expensive, and the chance we'd find the end page again is -// relatively high for small ranges) -// -// two initial interpolation-style probes are used at the start of the search -// to try to bound either side of the binary search sensibly, while still -// working in O(log n) time if they fail. - -static int get_seek_page_info(stb_vorbis *f, ProbedPage *z) -{ - uint8 header[27], lacing[255]; - int i,len; - - // record where the page starts - z->page_start = stb_vorbis_get_file_offset(f); - - // parse the header - getn(f, header, 27); - if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S') - return 0; - getn(f, lacing, header[26]); - - // determine the length of the payload - len = 0; - for (i=0; i < header[26]; ++i) - len += lacing[i]; - - // this implies where the page ends - z->page_end = z->page_start + 27 + header[26] + len; - - // read the last-decoded sample out of the data - z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24); - - // restore file state to where we were - set_file_offset(f, z->page_start); - return 1; -} - -// rarely used function to seek back to the preceding page while finding the -// start of a packet -static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset) -{ - unsigned int previous_safe, end; - - // now we want to seek back 64K from the limit - if (limit_offset >= 65536 && limit_offset-65536 >= f->first_audio_page_offset) - previous_safe = limit_offset - 65536; - else - previous_safe = f->first_audio_page_offset; - - set_file_offset(f, previous_safe); - - while (vorbis_find_page(f, &end, NULL)) { - if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset) - return 1; - set_file_offset(f, end); - } - - return 0; -} - -// implements the search logic for finding a page and starting decoding. if -// the function succeeds, current_loc_valid will be true and current_loc will -// be less than or equal to the provided sample number (the closer the -// better). -static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number) -{ - ProbedPage left, right, mid; - int i, start_seg_with_known_loc, end_pos, page_start; - uint32 delta, stream_length, padding, last_sample_limit; - double offset = 0.0, bytes_per_sample = 0.0; - int probe = 0; - - // find the last page and validate the target sample - stream_length = stb_vorbis_stream_length_in_samples(f); - if (stream_length == 0) return error(f, VORBIS_seek_without_length); - if (sample_number > stream_length) return error(f, VORBIS_seek_invalid); - - // this is the maximum difference between the window-center (which is the - // actual granule position value), and the right-start (which the spec - // indicates should be the granule position (give or take one)). - padding = ((f->blocksize_1 - f->blocksize_0) >> 2); - if (sample_number < padding) - last_sample_limit = 0; - else - last_sample_limit = sample_number - padding; - - left = f->p_first; - while (left.last_decoded_sample == ~0U) { - // (untested) the first page does not have a 'last_decoded_sample' - set_file_offset(f, left.page_end); - if (!get_seek_page_info(f, &left)) goto error; - } - - right = f->p_last; - assert(right.last_decoded_sample != ~0U); - - // starting from the start is handled differently - if (last_sample_limit <= left.last_decoded_sample) { - if (stb_vorbis_seek_start(f)) { - if (f->current_loc > sample_number) - return error(f, VORBIS_seek_failed); - return 1; - } - return 0; - } - - while (left.page_end != right.page_start) { - assert(left.page_end < right.page_start); - // search range in bytes - delta = right.page_start - left.page_end; - if (delta <= 65536) { - // there's only 64K left to search - handle it linearly - set_file_offset(f, left.page_end); - } else { - if (probe < 2) { - if (probe == 0) { - // first probe (interpolate) - double data_bytes = right.page_end - left.page_start; - bytes_per_sample = data_bytes / right.last_decoded_sample; - offset = left.page_start + bytes_per_sample * (last_sample_limit - left.last_decoded_sample); - } else { - // second probe (try to bound the other side) - double error = ((double) last_sample_limit - mid.last_decoded_sample) * bytes_per_sample; - if (error >= 0 && error < 8000) error = 8000; - if (error < 0 && error > -8000) error = -8000; - offset += error * 2; - } - - // ensure the offset is valid - if (offset < left.page_end) - offset = left.page_end; - if (offset > right.page_start - 65536) - offset = right.page_start - 65536; - - set_file_offset(f, (unsigned int) offset); - } else { - // binary search for large ranges (offset by 32K to ensure - // we don't hit the right page) - set_file_offset(f, left.page_end + (delta / 2) - 32768); - } - - if (!vorbis_find_page(f, NULL, NULL)) goto error; - } - - for (;;) { - if (!get_seek_page_info(f, &mid)) goto error; - if (mid.last_decoded_sample != ~0U) break; - // (untested) no frames end on this page - set_file_offset(f, mid.page_end); - assert(mid.page_start < right.page_start); - } - - // if we've just found the last page again then we're in a tricky file, - // and we're close enough (if it wasn't an interpolation probe). - if (mid.page_start == right.page_start) { - if (probe >= 2 || delta <= 65536) - break; - } else { - if (last_sample_limit < mid.last_decoded_sample) - right = mid; - else - left = mid; - } - - ++probe; - } - - // seek back to start of the last packet - page_start = left.page_start; - set_file_offset(f, page_start); - if (!start_page(f)) return error(f, VORBIS_seek_failed); - end_pos = f->end_seg_with_known_loc; - assert(end_pos >= 0); - - for (;;) { - for (i = end_pos; i > 0; --i) - if (f->segments[i-1] != 255) - break; - - start_seg_with_known_loc = i; - - if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet)) - break; - - // (untested) the final packet begins on an earlier page - if (!go_to_page_before(f, page_start)) - goto error; - - page_start = stb_vorbis_get_file_offset(f); - if (!start_page(f)) goto error; - end_pos = f->segment_count - 1; - } - - // prepare to start decoding - f->current_loc_valid = FALSE; - f->last_seg = FALSE; - f->valid_bits = 0; - f->packet_bytes = 0; - f->bytes_in_seg = 0; - f->previous_length = 0; - f->next_seg = start_seg_with_known_loc; - - for (i = 0; i < start_seg_with_known_loc; i++) - skip(f, f->segments[i]); - - // start decoding (optimizable - this frame is generally discarded) - if (!vorbis_pump_first_frame(f)) - return 0; - if (f->current_loc > sample_number) - return error(f, VORBIS_seek_failed); - return 1; - -error: - // try to restore the file to a valid state - stb_vorbis_seek_start(f); - return error(f, VORBIS_seek_failed); -} - -// the same as vorbis_decode_initial, but without advancing -static int peek_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) -{ - int bits_read, bytes_read; - - if (!vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode)) - return 0; - - // either 1 or 2 bytes were read, figure out which so we can rewind - bits_read = 1 + ilog(f->mode_count-1); - if (f->mode_config[*mode].blockflag) - bits_read += 2; - bytes_read = (bits_read + 7) / 8; - - f->bytes_in_seg += bytes_read; - f->packet_bytes -= bytes_read; - skip(f, -bytes_read); - if (f->next_seg == -1) - f->next_seg = f->segment_count - 1; - else - f->next_seg--; - f->valid_bits = 0; - - return 1; -} - -int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) -{ - uint32 max_frame_samples; - - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - - // fast page-level search - if (!seek_to_sample_coarse(f, sample_number)) - return 0; - - assert(f->current_loc_valid); - assert(f->current_loc <= sample_number); - - // linear search for the relevant packet - max_frame_samples = (f->blocksize_1*3 - f->blocksize_0) >> 2; - while (f->current_loc < sample_number) { - int left_start, left_end, right_start, right_end, mode, frame_samples; - if (!peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) - return error(f, VORBIS_seek_failed); - // calculate the number of samples returned by the next frame - frame_samples = right_start - left_start; - if (f->current_loc + frame_samples > sample_number) { - return 1; // the next frame will contain the sample - } else if (f->current_loc + frame_samples + max_frame_samples > sample_number) { - // there's a chance the frame after this could contain the sample - vorbis_pump_first_frame(f); - } else { - // this frame is too early to be relevant - f->current_loc += frame_samples; - f->previous_length = 0; - maybe_start_packet(f); - flush_packet(f); - } - } - // the next frame should start with the sample - if (f->current_loc != sample_number) return error(f, VORBIS_seek_failed); - return 1; -} - -int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) -{ - if (!stb_vorbis_seek_frame(f, sample_number)) - return 0; - - if (sample_number != f->current_loc) { - int n; - uint32 frame_start = f->current_loc; - stb_vorbis_get_frame_float(f, &n, NULL); - assert(sample_number > frame_start); - assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end); - f->channel_buffer_start += (sample_number - frame_start); - } - - return 1; -} - -int stb_vorbis_seek_start(stb_vorbis *f) -{ - if (IS_PUSH_MODE(f)) { return error(f, VORBIS_invalid_api_mixing); } - set_file_offset(f, f->first_audio_page_offset); - f->previous_length = 0; - f->first_decode = TRUE; - f->next_seg = -1; - return vorbis_pump_first_frame(f); -} - -unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) -{ - unsigned int restore_offset, previous_safe; - unsigned int end, last_page_loc; - - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - if (!f->total_samples) { - unsigned int last; - uint32 lo,hi; - char header[6]; - - // first, store the current decode position so we can restore it - restore_offset = stb_vorbis_get_file_offset(f); - - // now we want to seek back 64K from the end (the last page must - // be at most a little less than 64K, but let's allow a little slop) - if (f->stream_len >= 65536 && f->stream_len-65536 >= f->first_audio_page_offset) - previous_safe = f->stream_len - 65536; - else - previous_safe = f->first_audio_page_offset; - - set_file_offset(f, previous_safe); - // previous_safe is now our candidate 'earliest known place that seeking - // to will lead to the final page' - - if (!vorbis_find_page(f, &end, &last)) { - // if we can't find a page, we're hosed! - f->error = VORBIS_cant_find_last_page; - f->total_samples = 0xffffffff; - goto done; - } - - // check if there are more pages - last_page_loc = stb_vorbis_get_file_offset(f); - - // stop when the last_page flag is set, not when we reach eof; - // this allows us to stop short of a 'file_section' end without - // explicitly checking the length of the section - while (!last) { - set_file_offset(f, end); - if (!vorbis_find_page(f, &end, &last)) { - // the last page we found didn't have the 'last page' flag - // set. whoops! - break; - } - //previous_safe = last_page_loc+1; // NOTE: not used after this point, but note for debugging - last_page_loc = stb_vorbis_get_file_offset(f); - } - - set_file_offset(f, last_page_loc); - - // parse the header - getn(f, (unsigned char *)header, 6); - // extract the absolute granule position - lo = get32(f); - hi = get32(f); - if (lo == 0xffffffff && hi == 0xffffffff) { - f->error = VORBIS_cant_find_last_page; - f->total_samples = SAMPLE_unknown; - goto done; - } - if (hi) - lo = 0xfffffffe; // saturate - f->total_samples = lo; - - f->p_last.page_start = last_page_loc; - f->p_last.page_end = end; - f->p_last.last_decoded_sample = lo; - - done: - set_file_offset(f, restore_offset); - } - return f->total_samples == SAMPLE_unknown ? 0 : f->total_samples; -} - -float stb_vorbis_stream_length_in_seconds(stb_vorbis *f) -{ - return stb_vorbis_stream_length_in_samples(f) / (float) f->sample_rate; -} - - - -int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output) -{ - int len, right,left,i; - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - - if (!vorbis_decode_packet(f, &len, &left, &right)) { - f->channel_buffer_start = f->channel_buffer_end = 0; - return 0; - } - - len = vorbis_finish_frame(f, len, left, right); - for (i=0; i < f->channels; ++i) - f->outputs[i] = f->channel_buffers[i] + left; - - f->channel_buffer_start = left; - f->channel_buffer_end = left+len; - - if (channels) *channels = f->channels; - if (output) *output = f->outputs; - return len; -} - -#ifndef STB_VORBIS_NO_STDIO - -stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length) -{ - stb_vorbis *f, p; - vorbis_init(&p, alloc); - p.f = file; - p.f_start = (uint32) ftell(file); - p.stream_len = length; - p.close_on_free = close_on_free; - if (start_decoder(&p)) { - f = vorbis_alloc(&p); - if (f) { - *f = p; - vorbis_pump_first_frame(f); - return f; - } - } - if (error) *error = p.error; - vorbis_deinit(&p); - return NULL; -} - -stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc) -{ - unsigned int len, start; - start = (unsigned int) ftell(file); - fseek(file, 0, SEEK_END); - len = (unsigned int) (ftell(file) - start); - fseek(file, start, SEEK_SET); - return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); -} - -stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc) -{ - FILE *f; -#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__) - if (0 != fopen_s(&f, filename, "rb")) - f = NULL; -#else - f = fopen(filename, "rb"); -#endif - if (f) - return stb_vorbis_open_file(f, TRUE, error, alloc); - if (error) *error = VORBIS_file_open_failure; - return NULL; -} -#endif // STB_VORBIS_NO_STDIO - -stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc) -{ - stb_vorbis *f, p; - if (!data) { - if (error) *error = VORBIS_unexpected_eof; - return NULL; - } - vorbis_init(&p, alloc); - p.stream = (uint8 *) data; - p.stream_end = (uint8 *) data + len; - p.stream_start = (uint8 *) p.stream; - p.stream_len = len; - p.push_mode = FALSE; - if (start_decoder(&p)) { - f = vorbis_alloc(&p); - if (f) { - *f = p; - vorbis_pump_first_frame(f); - if (error) *error = VORBIS__no_error; - return f; - } - } - if (error) *error = p.error; - vorbis_deinit(&p); - return NULL; -} - -#ifndef STB_VORBIS_NO_INTEGER_CONVERSION -#define PLAYBACK_MONO 1 -#define PLAYBACK_LEFT 2 -#define PLAYBACK_RIGHT 4 - -#define L (PLAYBACK_LEFT | PLAYBACK_MONO) -#define C (PLAYBACK_LEFT | PLAYBACK_RIGHT | PLAYBACK_MONO) -#define R (PLAYBACK_RIGHT | PLAYBACK_MONO) - -static int8 channel_position[7][6] = -{ - { 0 }, - { C }, - { L, R }, - { L, C, R }, - { L, R, L, R }, - { L, C, R, L, R }, - { L, C, R, L, R, C }, -}; - - -#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT - typedef union { - float f; - int i; - } float_conv; - typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4]; - #define FASTDEF(x) float_conv x - // add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round - #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT)) - #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22)) - #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s)) - #define check_endianness() -#else - #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s)))) - #define check_endianness() - #define FASTDEF(x) -#endif - -static void copy_samples(short *dest, float *src, int len) -{ - int i; - check_endianness(); - for (i=0; i < len; ++i) { - FASTDEF(temp); - int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - dest[i] = v; - } -} - -static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len) -{ - #define STB_BUFFER_SIZE 32 - float buffer[STB_BUFFER_SIZE]; - int i,j,o,n = STB_BUFFER_SIZE; - check_endianness(); - for (o = 0; o < len; o += STB_BUFFER_SIZE) { - memset(buffer, 0, sizeof(buffer)); - if (o + n > len) n = len - o; - for (j=0; j < num_c; ++j) { - if (channel_position[num_c][j] & mask) { - for (i=0; i < n; ++i) - buffer[i] += data[j][d_offset+o+i]; - } - } - for (i=0; i < n; ++i) { - FASTDEF(temp); - int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - output[o+i] = v; - } - } - #undef STB_BUFFER_SIZE -} - -static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len) -{ - #define STB_BUFFER_SIZE 32 - float buffer[STB_BUFFER_SIZE]; - int i,j,o,n = STB_BUFFER_SIZE >> 1; - // o is the offset in the source data - check_endianness(); - for (o = 0; o < len; o += STB_BUFFER_SIZE >> 1) { - // o2 is the offset in the output data - int o2 = o << 1; - memset(buffer, 0, sizeof(buffer)); - if (o + n > len) n = len - o; - for (j=0; j < num_c; ++j) { - int m = channel_position[num_c][j] & (PLAYBACK_LEFT | PLAYBACK_RIGHT); - if (m == (PLAYBACK_LEFT | PLAYBACK_RIGHT)) { - for (i=0; i < n; ++i) { - buffer[i*2+0] += data[j][d_offset+o+i]; - buffer[i*2+1] += data[j][d_offset+o+i]; - } - } else if (m == PLAYBACK_LEFT) { - for (i=0; i < n; ++i) { - buffer[i*2+0] += data[j][d_offset+o+i]; - } - } else if (m == PLAYBACK_RIGHT) { - for (i=0; i < n; ++i) { - buffer[i*2+1] += data[j][d_offset+o+i]; - } - } - } - for (i=0; i < (n<<1); ++i) { - FASTDEF(temp); - int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - output[o2+i] = v; - } - } - #undef STB_BUFFER_SIZE -} - -static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples) -{ - int i; - if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { - static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} }; - for (i=0; i < buf_c; ++i) - compute_samples(channel_selector[buf_c][i], buffer[i]+b_offset, data_c, data, d_offset, samples); - } else { - int limit = buf_c < data_c ? buf_c : data_c; - for (i=0; i < limit; ++i) - copy_samples(buffer[i]+b_offset, data[i]+d_offset, samples); - for ( ; i < buf_c; ++i) - memset(buffer[i]+b_offset, 0, sizeof(short) * samples); - } -} - -int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples) -{ - float **output = NULL; - int len = stb_vorbis_get_frame_float(f, NULL, &output); - if (len > num_samples) len = num_samples; - if (len) - convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len); - return len; -} - -static void convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len) -{ - int i; - check_endianness(); - if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { - assert(buf_c == 2); - for (i=0; i < buf_c; ++i) - compute_stereo_samples(buffer, data_c, data, d_offset, len); - } else { - int limit = buf_c < data_c ? buf_c : data_c; - int j; - for (j=0; j < len; ++j) { - for (i=0; i < limit; ++i) { - FASTDEF(temp); - float f = data[i][d_offset+j]; - int v = FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - *buffer++ = v; - } - for ( ; i < buf_c; ++i) - *buffer++ = 0; - } - } -} - -int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts) -{ - float **output; - int len; - if (num_c == 1) return stb_vorbis_get_frame_short(f,num_c,&buffer, num_shorts); - len = stb_vorbis_get_frame_float(f, NULL, &output); - if (len) { - if (len*num_c > num_shorts) len = num_shorts / num_c; - convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len); - } - return len; -} - -int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts) -{ - float **outputs; - int len = num_shorts / channels; - int n=0; - while (n < len) { - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= len) k = len - n; - if (k) - convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, k); - buffer += k*channels; - n += k; - f->channel_buffer_start += k; - if (n == len) break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; - } - return n; -} - -int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len) -{ - float **outputs; - int n=0; - while (n < len) { - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= len) k = len - n; - if (k) - convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k); - n += k; - f->channel_buffer_start += k; - if (n == len) break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; - } - return n; -} - -#ifndef STB_VORBIS_NO_STDIO -int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output) -{ - int data_len, offset, total, limit, error; - short *data; - stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL); - if (v == NULL) return -1; - limit = v->channels * 4096; - *channels = v->channels; - if (sample_rate) - *sample_rate = v->sample_rate; - offset = data_len = 0; - total = limit; - data = (short *) malloc(total * sizeof(*data)); - if (data == NULL) { - stb_vorbis_close(v); - return -2; - } - for (;;) { - int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); - if (n == 0) break; - data_len += n; - offset += n * v->channels; - if (offset + limit > total) { - short *data2; - total *= 2; - data2 = (short *) realloc(data, total * sizeof(*data)); - if (data2 == NULL) { - free(data); - stb_vorbis_close(v); - return -2; - } - data = data2; - } - } - *output = data; - stb_vorbis_close(v); - return data_len; -} -#endif // NO_STDIO - -int stb_vorbis_decode_memory(const uint8 *mem, int len, int *channels, int *sample_rate, short **output) -{ - int data_len, offset, total, limit, error; - short *data; - stb_vorbis *v = stb_vorbis_open_memory(mem, len, &error, NULL); - if (v == NULL) return -1; - limit = v->channels * 4096; - *channels = v->channels; - if (sample_rate) - *sample_rate = v->sample_rate; - offset = data_len = 0; - total = limit; - data = (short *) malloc(total * sizeof(*data)); - if (data == NULL) { - stb_vorbis_close(v); - return -2; - } - for (;;) { - int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); - if (n == 0) break; - data_len += n; - offset += n * v->channels; - if (offset + limit > total) { - short *data2; - total *= 2; - data2 = (short *) realloc(data, total * sizeof(*data)); - if (data2 == NULL) { - free(data); - stb_vorbis_close(v); - return -2; - } - data = data2; - } - } - *output = data; - stb_vorbis_close(v); - return data_len; -} -#endif // STB_VORBIS_NO_INTEGER_CONVERSION - -int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats) -{ - float **outputs; - int len = num_floats / channels; - int n=0; - int z = f->channels; - if (z > channels) z = channels; - while (n < len) { - int i,j; - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= len) k = len - n; - for (j=0; j < k; ++j) { - for (i=0; i < z; ++i) - *buffer++ = f->channel_buffers[i][f->channel_buffer_start+j]; - for ( ; i < channels; ++i) - *buffer++ = 0; - } - n += k; - f->channel_buffer_start += k; - if (n == len) - break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) - break; - } - return n; -} - -int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples) -{ - float **outputs; - int n=0; - int z = f->channels; - if (z > channels) z = channels; - while (n < num_samples) { - int i; - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= num_samples) k = num_samples - n; - if (k) { - for (i=0; i < z; ++i) - memcpy(buffer[i]+n, f->channel_buffers[i]+f->channel_buffer_start, sizeof(float)*k); - for ( ; i < channels; ++i) - memset(buffer[i]+n, 0, sizeof(float) * k); - } - n += k; - f->channel_buffer_start += k; - if (n == num_samples) - break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) - break; - } - return n; -} -#endif // STB_VORBIS_NO_PULLDATA_API - -/* Version history - 1.17 - 2019-07-08 - fix CVE-2019-13217, -13218, -13219, -13220, -13221, -13222, -13223 - found with Mayhem by ForAllSecure - 1.16 - 2019-03-04 - fix warnings - 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found - 1.14 - 2018-02-11 - delete bogus dealloca usage - 1.13 - 2018-01-29 - fix truncation of last frame (hopefully) - 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files - 1.11 - 2017-07-23 - fix MinGW compilation - 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory - 1.09 - 2016-04-04 - back out 'avoid discarding last frame' fix from previous version - 1.08 - 2016-04-02 - fixed multiple warnings; fix setup memory leaks; - avoid discarding last frame of audio data - 1.07 - 2015-01-16 - fixed some warnings, fix mingw, const-correct API - some more crash fixes when out of memory or with corrupt files - 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson) - some crash fixes when out of memory or with corrupt files - 1.05 - 2015-04-19 - don't define __forceinline if it's redundant - 1.04 - 2014-08-27 - fix missing const-correct case in API - 1.03 - 2014-08-07 - Warning fixes - 1.02 - 2014-07-09 - Declare qsort compare function _cdecl on windows - 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float - 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in multichannel - (API change) report sample rate for decode-full-file funcs - 0.99996 - bracket #include for macintosh compilation by Laurent Gomila - 0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem - 0.99994 - change fast-float-to-int to work in single-precision FPU mode, remove endian-dependence - 0.99993 - remove assert that fired on legal files with empty tables - 0.99992 - rewind-to-start - 0.99991 - bugfix to stb_vorbis_get_samples_short by Bernhard Wodo - 0.9999 - (should have been 0.99990) fix no-CRT support, compiling as C++ - 0.9998 - add a full-decode function with a memory source - 0.9997 - fix a bug in the read-from-FILE case in 0.9996 addition - 0.9996 - query length of vorbis stream in samples/seconds - 0.9995 - bugfix to another optimization that only happened in certain files - 0.9994 - bugfix to one of the optimizations that caused significant (but inaudible?) errors - 0.9993 - performance improvements; runs in 99% to 104% of time of reference implementation - 0.9992 - performance improvement of IMDCT; now performs close to reference implementation - 0.9991 - performance improvement of IMDCT - 0.999 - (should have been 0.9990) performance improvement of IMDCT - 0.998 - no-CRT support from Casey Muratori - 0.997 - bugfixes for bugs found by Terje Mathisen - 0.996 - bugfix: fast-huffman decode initialized incorrectly for sparse codebooks; fixing gives 10% speedup - found by Terje Mathisen - 0.995 - bugfix: fix to 'effective' overrun detection - found by Terje Mathisen - 0.994 - bugfix: garbage decode on final VQ symbol of a non-multiple - found by Terje Mathisen - 0.993 - bugfix: pushdata API required 1 extra byte for empty page (failed to consume final page if empty) - found by Terje Mathisen - 0.992 - fixes for MinGW warning - 0.991 - turn fast-float-conversion on by default - 0.990 - fix push-mode seek recovery if you seek into the headers - 0.98b - fix to bad release of 0.98 - 0.98 - fix push-mode seek recovery; robustify float-to-int and support non-fast mode - 0.97 - builds under c++ (typecasting, don't use 'class' keyword) - 0.96 - somehow MY 0.95 was right, but the web one was wrong, so here's my 0.95 rereleased as 0.96, fixes a typo in the clamping code - 0.95 - clamping code for 16-bit functions - 0.94 - not publically released - 0.93 - fixed all-zero-floor case (was decoding garbage) - 0.92 - fixed a memory leak - 0.91 - conditional compiles to omit parts of the API and the infrastructure to support them: STB_VORBIS_NO_PULLDATA_API, STB_VORBIS_NO_PUSHDATA_API, STB_VORBIS_NO_STDIO, STB_VORBIS_NO_INTEGER_CONVERSION - 0.90 - first public release -*/ - -#endif // STB_VORBIS_HEADER_ONLY - - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/scene.nim --- a/src/semicongine/scene.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -import std/tables -import std/sequtils -import std/strformat -import std/hashes - -import ./core -import ./mesh -import ./material - -type - Scene* = object - name*: string - shaderGlobals*: Table[string, DataList] - meshes*: seq[Mesh] - dirtyShaderGlobals: seq[string] - loaded*: bool = false - -proc add*(scene: var Scene, mesh: MeshObject) = - assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add meshes" - var tmp = new Mesh - tmp[] = mesh - scene.meshes.add tmp - -proc add*(scene: var Scene, mesh: Mesh) = - assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add meshes" - assert not mesh.isNil, "Cannot add a mesh that is 'nil'" - scene.meshes.add mesh - -proc add*(scene: var Scene, meshes: seq[Mesh]) = - assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add meshes" - for mesh in meshes: - assert not mesh.isNil, "Cannot add a mesh that is 'nil'" - scene.meshes.add meshes - -# generic way to add objects that have a mesh-attribute -proc add*[T](scene: var Scene, obj: T) = - assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add meshes" - for name, value in obj.fieldPairs: - when typeof(value) is Mesh: - assert not value.isNil, "Cannot add a mesh that is 'nil': " & name - scene.meshes.add value - when typeof(value) is seq[Mesh]: - assert not value.isNil, &"Cannot add a mesh that is 'nil': " & name - scene.meshes.add value - -proc addShaderGlobal*[T](scene: var Scene, name: string, data: T) = - assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add shader values" - scene.shaderGlobals[name] = initDataList(thetype=getDataType[T]()) - setValues(scene.shaderGlobals[name], @[data]) - scene.dirtyShaderGlobals.add name - -proc addShaderGlobalArray*[T](scene: var Scene, name: string, data: openArray[T]) = - assert not scene.loaded, &"Scene {scene.name} has already been loaded, cannot add shader values" - scene.shaderGlobals[name] = initDataList(data) - scene.dirtyShaderGlobals.add name - -func getShaderGlobal*[T](scene: Scene, name: string): T = - getValues[T](scene.shaderGlobals[name])[0] - -func getShaderGlobalArray*[T](scene: Scene, name: string): seq[T] = - getValues[T](scene.shaderGlobals[name]) - -proc setShaderGlobal*[T](scene: var Scene, name: string, value: T) = - setValues[T](scene.shaderGlobals[name], @[value]) - if not scene.dirtyShaderGlobals.contains(name): - scene.dirtyShaderGlobals.add name - -proc setShaderGlobalArray*[T](scene: var Scene, name: string, value: seq[T]) = - setValues[T](scene.shaderGlobals[name], value) - if not scene.dirtyShaderGlobals.contains(name): - scene.dirtyShaderGlobals.add name - -func dirtyShaderGlobals*(scene: Scene): seq[string] = - scene.dirtyShaderGlobals - -func clearDirtyShaderGlobals*(scene: var Scene) = - scene.dirtyShaderGlobals.reset - -func hash*(scene: Scene): Hash = - hash(scene.name) - -func `==`*(a, b: Scene): bool = - a.name == b.name - -func usesMaterial*(scene: Scene, materialType: MaterialType): bool = - return scene.meshes.anyIt(it.material.theType == materialType) - -func getMaterials*(scene: Scene, materialType: MaterialType): seq[MaterialData] = - for mesh in scene.meshes: - if mesh.material.theType == materialType and (not result.contains(mesh.material)): - result.add mesh.material diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/settings.nim --- a/src/semicongine/settings.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -import std/logging -import std/streams -import std/parsecfg -import std/strutils -import std/parseutils -import std/strformat -import std/tables -import std/os - -import ./core - -when CONFIGHOTRELOAD: - var - configUpdates: Channel[(string, string)] - configUpdates.open() - -# runtime configuration -# ===================== -# namespace is the path from the CONFIGROOT to the according settings file without the file extension -# a settings file must always have the extension CONFIGEXTENSION -# a fully qualified settings identifier can be in the form {namespace}.{section}.{key} -# {key} and {section} may not contain dots - -# a "namespace" is the path from the settings root to an *.CONFIGEXTENSION file, without the file extension -# settings is a namespace <-> settings mapping -var allsettings: Table[string, Config] - -proc configRoot(): string = - joinPath(absolutePath(getAppDir()), CONFIGROOT) - -proc getFile(namespace: string): string = - joinPath(configRoot(), namespace & "." & CONFIGEXTENSION) - -iterator walkConfigNamespaces(): string = - for file in walkDirRec(dir=configRoot(), relative=true, checkDir=true): - if file.endsWith("." & CONFIGEXTENSION): - yield file[0 ..< ^(CONFIGEXTENSION.len + 1)] - -proc loadAllConfig(): Table[string, Config] = - for ns in walkConfigNamespaces(): - result[ns] = ns.getFile().loadConfig() - -proc reloadSettings*() = - allsettings = loadAllConfig() - -proc configStr(key, section, namespace: string): string = - when CONFIGHOTRELOAD: - while configUpdates.peek() > 0: - let (updatedNamespace, updatedConfig) = configUpdates.recv() - allsettings[updatedNamespace] = loadConfig(newStringStream(updatedConfig)) - if not allsettings.hasKey(namespace): - raise newException(Exception, &"Settings {namespace}.{section}.{key} was not found") - allsettings[namespace].getSectionValue(section, key) - -proc setting*[T: int|float|string](key, section, namespace: string): T = - when T is int: - let value = configStr(key, section, namespace) - if parseInt(value, result) == 0: - raise newException(Exception, &"Unable to parse int from settings {namespace}.{section}.{key}: {value}") - elif T is float: - let value = configStr(key, section, namespace) - if parseFloat(value, result) == 0: - raise newException(Exception, &"Unable to parse float from settings {namespace}.{section}.{key}: {value}") - else: - result = configStr(key, section, namespace) - -proc setting*[T: int|float|string](identifier: string): T = - # identifier can be in the form: - # {namespace}.{key} - # {namespace}.{section}.{key} - let parts = identifier.rsplit(".") - if parts.len == 1: - raise newException(Exception, &"Setting with name {identifier} has no namespace") - if parts.len == 2: result = setting[T](parts[1], "", parts[0]) - else: result = setting[T](parts[^1], parts[^2], joinPath(parts[0 .. ^3])) - -proc hadConfigUpdate*(): bool = - when CONFIGHOTRELOAD == true: - result = configUpdates.peek() > 0 - -allsettings = loadAllConfig() - -when CONFIGHOTRELOAD == true: - import std/times - - proc configFileWatchdog() {.thread.} = - var configModTimes: Table[string, Time] - while true: - for namespace in walkConfigNamespaces(): - if not (namespace in configModTimes): - configModTimes[namespace] = Time() - let lastMod = namespace.getFile().getLastModificationTime() - if lastMod > configModTimes[namespace]: - configModTimes[namespace] = lastMod - let configStr = newFileStream(namespace.getFile()).readAll() - configUpdates.send((namespace, configStr)) - sleep CONFIGHOTRELOADINTERVAL - var thethread: Thread[void] - createThread(thethread, configFileWatchdog) - -if DEBUG: - setLogFilter(lvlAll) -else: - setLogFilter(lvlWarn) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/telemetry.nim --- a/src/semicongine/telemetry.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -# curl -X POST https://semicongine-telemetry.clients1.basx.dev/telemetry/telemetry/event/submit/log/test/1.0/2342343 -v -H "project-api-key: test-key-42" diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/text.nim --- a/src/semicongine/text.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -import std/tables -import std/unicode -import std/strformat - -import ./core -import ./mesh -import ./material -import ./vulkan/shader - -const SHADER_ATTRIB_PREFIX = "semicon_text_" -var instanceCounter = 0 - -type - TextAlignment = enum - Left - Center - Right - Textbox* = object - maxLen*: int - text: seq[Rune] - dirty: bool - alignment*: TextAlignment = Center - font*: Font - mesh*: Mesh - -const - TRANSFORM_ATTRIB = "transform" - POSITION_ATTRIB = SHADER_ATTRIB_PREFIX & "position" - UV_ATTRIB = SHADER_ATTRIB_PREFIX & "uv" - TEXT_MATERIAL_TYPE* = MaterialType( - name: "default-text-material-type", - vertexAttributes: {TRANSFORM_ATTRIB: Mat4F32, POSITION_ATTRIB: Vec3F32, UV_ATTRIB: Vec2F32}.toTable, - attributes: {"fontAtlas": TextureType}.toTable, - ) - TEXT_SHADER* = createShaderConfiguration( - inputs=[ - attr[Mat4](TRANSFORM_ATTRIB, memoryPerformanceHint=PreferFastWrite, perInstance=true), - attr[Vec3f](POSITION_ATTRIB, memoryPerformanceHint=PreferFastWrite), - attr[Vec2f](UV_ATTRIB, memoryPerformanceHint=PreferFastWrite), - ], - intermediates=[attr[Vec2f]("uvFrag")], - outputs=[attr[Vec4f]("color")], - samplers=[attr[Texture]("fontAtlas")], - vertexCode= &"""gl_Position = vec4({POSITION_ATTRIB}, 1.0) * {TRANSFORM_ATTRIB}; uvFrag = {UV_ATTRIB};""", - fragmentCode= &"""color = texture(fontAtlas, uvFrag);""", - ) - -proc updateMesh(textbox: var Textbox) = - - # pre-calculate text-width - var width = 0'f32 - for i in 0 ..< min(textbox.text.len, textbox.maxLen): - width += textbox.font.glyphs[textbox.text[i]].advance - if i < textbox.text.len - 1: - width += textbox.font.kerning[(textbox.text[i], textbox.text[i + 1])] - - let centerX = width / 2 - let centerY = textbox.font.maxHeight / 2 - - var offsetX = 0'f32 - for i in 0 ..< textbox.maxLen: - let vertexOffset = i * 4 - if i < textbox.text.len: - let - glyph = textbox.font.glyphs[textbox.text[i]] - left = offsetX + glyph.leftOffset - right = offsetX + glyph.leftOffset + glyph.dimension.x - top = glyph.topOffset - bottom = glyph.topOffset + glyph.dimension.y - - textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f(left - centerX, bottom + centerY) - textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f(left - centerX, top + centerY) - textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f(right - centerX, top + centerY) - textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f(right - centerX, bottom + centerY) - - textbox.mesh[UV_ATTRIB, vertexOffset + 0] = glyph.uvs[0] - textbox.mesh[UV_ATTRIB, vertexOffset + 1] = glyph.uvs[1] - textbox.mesh[UV_ATTRIB, vertexOffset + 2] = glyph.uvs[2] - textbox.mesh[UV_ATTRIB, vertexOffset + 3] = glyph.uvs[3] - - offsetX += glyph.advance - if i < textbox.text.len - 1: - offsetX += textbox.font.kerning[(textbox.text[i], textbox.text[i + 1])] - else: - textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f() - textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f() - textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f() - textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f() - - -func text*(textbox: Textbox): seq[Rune] = - textbox.text - -proc `text=`*(textbox: var Textbox, text: seq[Rune]) = - textbox.text = text - textbox.updateMesh() -proc `text=`*(textbox: var Textbox, text: string) = - `text=`(textbox, text.toRunes) - -proc initTextbox*(maxLen: int, font: Font, text="".toRunes): Textbox = - var - positions = newSeq[Vec3f](int(maxLen * 4)) - indices: seq[array[3, uint16]] - uvs = newSeq[Vec2f](int(maxLen * 4)) - for i in 0 ..< maxLen: - let offset = i * 4 - indices.add [ - [uint16(offset + 0), uint16(offset + 1), uint16(offset + 2)], - [uint16(offset + 2), uint16(offset + 3), uint16(offset + 0)], - ] - - result = Textbox(maxLen: maxLen, text: text, font: font, dirty: true) - result.mesh = newMesh(positions = positions, indices = indices, uvs = uvs, name = &"textbox-{instanceCounter}") - inc instanceCounter - result.mesh[].renameAttribute("position", POSITION_ATTRIB) - result.mesh[].renameAttribute("uv", UV_ATTRIB) - result.mesh.material = MaterialData( - theType: TEXT_MATERIAL_TYPE, - name: font.name & " text", - attributes: {"fontAtlas": initDataList(@[font.fontAtlas])}.toTable, - ) - - result.updateMesh() - -proc initTextbox*(maxLen: int, font: Font, text=""): Textbox = - initTextbox(maxLen=maxLen, font=font, text=text.toRunes) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan.nim --- a/src/semicongine/vulkan.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -import ./vulkan/instance -import ./vulkan/physicaldevice -import ./vulkan/device -import ./vulkan/swapchain -import ./vulkan/renderpass -import ./vulkan/framebuffer -import ./vulkan/commandbuffer -import ./vulkan/syncing -import ./vulkan/shader -import ./vulkan/descriptor -import ./vulkan/pipeline -import ./vulkan/buffer -import ./vulkan/memory - -export instance -export physicaldevice -export device -export swapchain -export renderpass -export framebuffer -export commandbuffer -export syncing -export shader -export descriptor -export pipeline -export buffer -export memory - diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/buffer.nim --- a/src/semicongine/vulkan/buffer.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -import std/strformat -import std/typetraits -import std/sequtils -import std/tables -import std/logging - -import ../core -import ./device -import ./memory -import ./physicaldevice -import ./commandbuffer - -type - Buffer* = object - device*: Device - vk*: VkBuffer - size*: int - usage*: seq[VkBufferUsageFlagBits] - case memoryAllocated*: bool - of false: discard - of true: - memory*: DeviceMemory - - -proc `==`*(a, b: Buffer): bool = - a.vk == b.vk - -func `$`*(buffer: Buffer): string = - &"Buffer(vk: {buffer.vk}, size: {buffer.size}, usage: {buffer.usage})" - -proc requirements(buffer: Buffer): MemoryRequirements = - assert buffer.vk.valid - assert buffer.device.vk.valid - var req: VkMemoryRequirements - buffer.device.vk.vkGetBufferMemoryRequirements(buffer.vk, addr req) - result.size = req.size - result.alignment = req.alignment - let memorytypes = buffer.device.physicaldevice.vk.getMemoryProperties().types - for i in 0 ..< sizeof(req.memoryTypeBits) * 8: - if ((req.memoryTypeBits shr i) and 1) == 1: - result.memoryTypes.add memorytypes[i] - -proc allocateMemory(buffer: var Buffer, requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool) = - assert buffer.device.vk.valid - assert buffer.memoryAllocated == false - - let requirements = buffer.requirements() - let memoryType = requirements.memoryTypes.selectBestMemoryType( - requireMappable=requireMappable, - preferVRAM=preferVRAM, - preferAutoFlush=preferAutoFlush - ) - - debug "Allocating memory for buffer: ", buffer.size, " bytes of type ", memoryType - # need to replace the whole buffer object, due to case statement - buffer = Buffer( - device: buffer.device, - vk: buffer.vk, - size: buffer.size, - usage: buffer.usage, - memoryAllocated: true, - memory: buffer.device.allocate(requirements.size, memoryType) - ) - checkVkResult buffer.device.vk.vkBindBufferMemory(buffer.vk, buffer.memory.vk, VkDeviceSize(0)) - -# currently no support for extended structure and concurrent/shared use -# (shardingMode = VK_SHARING_MODE_CONCURRENT not supported) -proc createBuffer*( - device: Device, - size: int, - usage: openArray[VkBufferUsageFlagBits], - requireMappable: bool, - preferVRAM: bool, - preferAutoFlush=true, -): Buffer = - assert device.vk.valid - assert size > 0 - - result.device = device - result.size = size - result.usage = usage.toSeq - if not requireMappable: - result.usage.add VK_BUFFER_USAGE_TRANSFER_DST_BIT - var createInfo = VkBufferCreateInfo( - sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - flags: VkBufferCreateFlags(0), - size: uint64(size), - usage: toBits(result.usage), - sharingMode: VK_SHARING_MODE_EXCLUSIVE, - ) - - checkVkResult vkCreateBuffer( - device=device.vk, - pCreateInfo=addr createInfo, - pAllocator=nil, - pBuffer=addr result.vk - ) - result.allocateMemory(requireMappable=requireMappable, preferVRAM=preferVRAM, preferAutoFlush=preferAutoFlush) - - -proc copy*(src, dst: Buffer, dstOffset=0) = - assert src.device.vk.valid - assert dst.device.vk.valid - assert src.device == dst.device - assert src.size <= dst.size - dstOffset - assert VK_BUFFER_USAGE_TRANSFER_SRC_BIT in src.usage - assert VK_BUFFER_USAGE_TRANSFER_DST_BIT in dst.usage - - var copyRegion = VkBufferCopy(size: VkDeviceSize(src.size), dstOffset: VkDeviceSize(dstOffset)) - withSingleUseCommandBuffer(src.device, true, commandBuffer): - commandBuffer.vkCmdCopyBuffer(src.vk, dst.vk, 1, addr(copyRegion)) - -proc destroy*(buffer: var Buffer) = - assert buffer.device.vk.valid - assert buffer.vk.valid - buffer.device.vk.vkDestroyBuffer(buffer.vk, nil) - if buffer.memoryAllocated: - assert buffer.memory.vk.valid - buffer.memory.free - buffer = Buffer( - device: buffer.device, - vk: buffer.vk, - size: buffer.size, - usage: buffer.usage, - memoryAllocated: false, - ) - buffer.vk.reset - -proc setData*(dst: Buffer, src: pointer, size: int, bufferOffset=0) = - assert bufferOffset + size <= dst.size - if dst.memory.canMap: - copyMem(cast[pointer](cast[int](dst.memory.data) + bufferOffset), src, size) - if dst.memory.needsFlushing: - dst.memory.flush() - else: # use staging buffer, slower but required if memory is not host visible - var stagingBuffer = dst.device.createBuffer(size, [VK_BUFFER_USAGE_TRANSFER_SRC_BIT], requireMappable=true, preferVRAM=false, preferAutoFlush=true) - setData(stagingBuffer, src, size, 0) - stagingBuffer.copy(dst, bufferOffset) - stagingBuffer.destroy() - -proc setData*[T: seq](dst: Buffer, src: ptr T, offset=0'u64) = - dst.setData(src, sizeof(get(genericParams(T), 0)) * src[].len, offset=offset) - -proc setData*[T](dst: Buffer, src: ptr T, offset=0'u64) = - dst.setData(src, sizeof(T), offset=offset) - diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/commandbuffer.nim --- a/src/semicongine/vulkan/commandbuffer.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -import ../core -import ./device -import ./physicaldevice - -type - CommandBufferPool* = object - device: Device - vk*: VkCommandPool - family*: QueueFamily - buffers*: seq[VkCommandBuffer] - -proc createCommandBufferPool*(device: Device, family: QueueFamily, nBuffers: int): CommandBufferPool = - assert device.vk.valid - var createInfo = VkCommandPoolCreateInfo( - sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT], - queueFamilyIndex: family.index, - ) - result.family = family - result.device = device - checkVkResult device.vk.vkCreateCommandPool(addr(createInfo), nil, addr(result.vk)) - - var allocInfo = VkCommandBufferAllocateInfo( - sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - commandPool: result.vk, - level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, - commandBufferCount: uint32(nBuffers), - ) - result.buffers = newSeq[VkCommandBuffer](nBuffers) - checkVkResult device.vk.vkAllocateCommandBuffers(addr(allocInfo), result.buffers.toCPointer) - - -template withSingleUseCommandBuffer*(device: Device, needsTransfer: bool, commandBuffer, body: untyped): untyped = - assert device.vk.valid - - var queue: Queue - for q in device.queues.values: - if q.family.canDoTransfer or not needsTransfer: - queue = q - break - if not queue.vk.valid: - raise newException(Exception, "No queue that supports buffer transfer") - - var - commandBufferPool = createCommandBufferPool(device, queue.family, 1) - commandBuffer = commandBufferPool.buffers[0] - beginInfo = VkCommandBufferBeginInfo( - sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT), - ) - checkVkResult commandBuffer.vkBeginCommandBuffer(addr(beginInfo)) - - block: - body - - checkVkResult commandBuffer.vkEndCommandBuffer() - var submitInfo = VkSubmitInfo( - sType: VK_STRUCTURE_TYPE_SUBMIT_INFO, - commandBufferCount: 1, - pCommandBuffers: addr(commandBuffer), - ) - checkVkResult queue.vk.vkQueueSubmit(1, addr(submitInfo), VkFence(0)) - checkVkResult queue.vk.vkQueueWaitIdle() - commandBufferPool.destroy() - -proc destroy*(commandpool: var CommandBufferPool) = - assert commandpool.device.vk.valid - assert commandpool.vk.valid - commandpool.device.vk.vkDestroyCommandPool(commandpool.vk, nil) - commandpool.vk.reset diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/descriptor.nim --- a/src/semicongine/vulkan/descriptor.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -import std/enumerate -import std/tables - -import ../core -import ./device -import ./buffer -import ./image - -type - DescriptorType* = enum - Uniform, ImageSampler - Descriptor* = object # "fields" of a DescriptorSetLayout - name*: string - count*: int - stages*: seq[VkShaderStageFlagBits] - case thetype*: DescriptorType - of Uniform: - buffer*: Buffer - offset*: int - size*: int - of ImageSampler: - imageviews*: seq[ImageView] - samplers*: seq[VulkanSampler] - DescriptorSet* = object # "instance" of a DescriptorSetLayout - vk*: VkDescriptorSet - layout*: DescriptorSetLayout - DescriptorSetLayout* = object # "type-description" of a DescriptorSet - device: Device - vk*: VkDescriptorSetLayout - descriptors*: seq[Descriptor] - DescriptorPool* = object # required for allocation of DescriptorSet - device: Device - vk*: VkDescriptorPool - maxSets*: int # maximum number of allocatable descriptor sets - counts*: seq[(VkDescriptorType, int)] # maximum number for each descriptor type to allocate - -const DESCRIPTOR_TYPE_MAP = { - Uniform: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - ImageSampler: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, -}.toTable - -func vkType(descriptor: Descriptor): VkDescriptorType = - DESCRIPTOR_TYPE_MAP[descriptor.thetype] - -proc createDescriptorSetLayout*(device: Device, descriptors: seq[Descriptor]): DescriptorSetLayout = - assert device.vk.valid - - result.device = device - result.descriptors = descriptors - - var layoutbindings: seq[VkDescriptorSetLayoutBinding] - for i, descriptor in enumerate(descriptors): - layoutbindings.add VkDescriptorSetLayoutBinding( - binding: uint32(i), - descriptorType: descriptor.vkType, - descriptorCount: uint32(descriptor.count), - stageFlags: toBits descriptor.stages, - pImmutableSamplers: nil, - ) - var layoutCreateInfo = VkDescriptorSetLayoutCreateInfo( - sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - bindingCount: uint32(layoutbindings.len), - pBindings: layoutbindings.toCPointer - ) - checkVkResult vkCreateDescriptorSetLayout(device.vk, addr(layoutCreateInfo), nil, addr(result.vk)) - -proc destroy*(descriptorSetLayout: var DescriptorSetLayout) = - assert descriptorSetLayout.device.vk.valid - assert descriptorSetLayout.vk.valid - descriptorSetLayout.device.vk.vkDestroyDescriptorSetLayout(descriptorSetLayout.vk, nil) - descriptorSetLayout.vk.reset - - -proc createDescriptorSetPool*(device: Device, counts: seq[(VkDescriptorType, int)], maxSets = 1000): DescriptorPool = - assert device.vk.valid - - result.device = device - result.maxSets = maxSets - result.counts = counts - - var poolSizes: seq[VkDescriptorPoolSize] - for (thetype, count) in result.counts: - poolSizes.add VkDescriptorPoolSize(thetype: thetype, descriptorCount: uint32(count)) - var poolInfo = VkDescriptorPoolCreateInfo( - sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - poolSizeCount: uint32(poolSizes.len), - pPoolSizes: poolSizes.toCPointer, - maxSets: uint32(result.maxSets), - ) - checkVkResult vkCreateDescriptorPool(result.device.vk, addr(poolInfo), nil, addr(result.vk)) - -proc reset*(pool: DescriptorPool) = - assert pool.device.vk.valid - assert pool.vk.valid - checkVkResult vkResetDescriptorPool(pool.device.vk, pool.vk, VkDescriptorPoolResetFlags(0)) - -proc destroy*(pool: var DescriptorPool) = - assert pool.device.vk.valid - assert pool.vk.valid - pool.device.vk.vkDestroyDescriptorPool(pool.vk, nil) - pool.vk.reset - -proc allocateDescriptorSet*(pool: DescriptorPool, layout: DescriptorSetLayout, nframes: int): seq[DescriptorSet] = - assert pool.device.vk.valid - assert pool.vk.valid - assert layout.device.vk.valid - assert layout.vk.valid - - var layouts: seq[VkDescriptorSetLayout] - var descriptorSets = newSeq[VkDescriptorSet](nframes) - for i in 0 ..< nframes: - layouts.add layout.vk - var allocInfo = VkDescriptorSetAllocateInfo( - sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - descriptorPool: pool.vk, - descriptorSetCount: uint32(layouts.len), - pSetLayouts: layouts.toCPointer, - ) - - checkVkResult vkAllocateDescriptorSets(pool.device.vk, addr(allocInfo), descriptorSets.toCPointer) - for descriptorSet in descriptorSets: - result.add DescriptorSet(vk: descriptorSet, layout: layout) - -proc writeDescriptorSet*(descriptorSet: DescriptorSet, bindingBase=0'u32) = - # assumes descriptors of the descriptorSet are arranged interleaved in buffer - assert descriptorSet.layout.device.vk.valid - assert descriptorSet.layout.vk.valid - assert descriptorSet.vk.valid - - var descriptorSetWrites: seq[VkWriteDescriptorSet] - var bufferInfos: seq[VkDescriptorBufferInfo] - - var i = bindingBase - # need to keep this sequence out of the loop, otherwise it will be - # gc-ed before the final update call and pointers are invalid :( - var imgInfos: seq[seq[VkDescriptorImageInfo]] - for descriptor in descriptorSet.layout.descriptors: - if descriptor.thetype == Uniform: - assert descriptor.buffer.vk.valid - bufferInfos.add VkDescriptorBufferInfo( - buffer: descriptor.buffer.vk, - offset: uint64(descriptor.offset), - range: uint64(descriptor.size), - ) - descriptorSetWrites.add VkWriteDescriptorSet( - sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - dstSet: descriptorSet.vk, - dstBinding: i, - dstArrayElement: 0, - descriptorType: descriptor.vkType, - descriptorCount: uint32(descriptor.count), - pBufferInfo: addr bufferInfos[^1], - ) - elif descriptor.thetype == ImageSampler: - var imgInfo: seq[VkDescriptorImageInfo] - for img_i in 0 ..< descriptor.count: - assert descriptor.imageviews[img_i].vk.valid - assert descriptor.samplers[img_i].vk.valid - imgInfo.add VkDescriptorImageInfo( - imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - imageView: descriptor.imageviews[img_i].vk, - sampler: descriptor.samplers[img_i].vk, - ) - imgInfos.add imgInfo - descriptorSetWrites.add VkWriteDescriptorSet( - sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - dstSet: descriptorSet.vk, - dstBinding: i, - dstArrayElement: 0, - descriptorType: descriptor.vkType, - descriptorCount: uint32(descriptor.count), - pImageInfo: imgInfos[^1].toCPointer, - ) - inc i - descriptorSet.layout.device.vk.vkUpdateDescriptorSets(uint32(descriptorSetWrites.len), descriptorSetWrites.toCPointer, 0, nil) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/device.nim --- a/src/semicongine/vulkan/device.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -import std/sequtils -import std/options -import std/tables - -import ../core -import ./instance -import ./physicaldevice - -type - Device* = object - physicalDevice*: PhysicalDevice - vk*: VkDevice - queues*: Table[QueueFamily, Queue] - enabledFeatures*: VkPhysicalDeviceFeatures - Queue* = object - vk*: VkQueue - family*: QueueFamily - presentation: bool - graphics: bool - -proc `$`*(device: Device): string = - "Device: vk=" & $device.vk - -proc createDevice*( - instance: Instance, - physicalDevice: PhysicalDevice, - enabledLayers: seq[string], - enabledExtensions: seq[string], - queueFamilies: seq[QueueFamily], -): Device = - assert instance.vk.valid - assert physicalDevice.vk.valid - assert queueFamilies.len > 0 - - result.physicalDevice = physicalDevice - var allExtensions = enabledExtensions & @["VK_KHR_swapchain"] - for extension in allExtensions: - instance.vk.loadExtension(extension) - var - enabledLayersC = allocCStringArray(enabledLayers) - enabledExtensionsC = allocCStringArray(allExtensions) - priority = 1'f32 - var deviceQueues: Table[QueueFamily, VkDeviceQueueCreateInfo] - for family in queueFamilies: - deviceQueues[family] = VkDeviceQueueCreateInfo( - sType: VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - queueFamilyIndex: family.index, - queueCount: 1, - pQueuePriorities: addr(priority), - ) - var queueList = deviceQueues.values.toSeq - - var uniformBufferLayoutFeature = VkPhysicalDeviceUniformBufferStandardLayoutFeatures( - stype:VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES, - uniformBufferStandardLayout: true, - ) - var features2 = VkPhysicalDeviceFeatures2( - stype: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, - pnext: addr uniformBufferLayoutFeature, - features: result.enabledFeatures, - ) - var createInfo = VkDeviceCreateInfo( - sType: VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - queueCreateInfoCount: uint32(queueList.len), - pQueueCreateInfos: queueList.toCPointer, - enabledLayerCount: uint32(enabledLayers.len), - ppEnabledLayerNames: enabledLayersC, - enabledExtensionCount: uint32(allExtensions.len), - ppEnabledExtensionNames: enabledExtensionsC, - pEnabledFeatures: nil, - pnext: addr features2, - ) - - checkVkResult vkCreateDevice( - physicalDevice=physicalDevice.vk, - pCreateInfo=addr createInfo, - pAllocator=nil, - pDevice=addr result.vk - ) - deallocCStringArray(enabledLayersC) - deallocCStringArray(enabledExtensionsC) - for family in deviceQueues.keys: - var queue: VkQueue - vkGetDeviceQueue(result.vk, family.index, 0, addr queue) - result.queues[family] = Queue(vk: queue, family: family, presentation: family.canDoPresentation(physicalDevice.surface), graphics: family.canDoGraphics()) - -func firstGraphicsQueue*(device: Device): Option[Queue] = - assert device.vk.valid - for family, queue in device.queues: - if queue.graphics: - return some(queue) - -proc firstPresentationQueue*(device: Device): Option[Queue] = - assert device.vk.valid - for family, queue in device.queues: - if queue.presentation: - return some(queue) - -proc destroy*(device: var Device) = - assert device.vk.valid - device.vk.vkDestroyDevice(nil) - device.vk.reset() diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/drawable.nim --- a/src/semicongine/vulkan/drawable.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -import std/tables -import std/strformat -import std/logging - -import ../core -import ./buffer - -type - Drawable* = object - name*: string - elementCount*: int # number of vertices or indices - bufferOffsets*: Table[VkPipeline, seq[(string, MemoryPerformanceHint, int)]] # list of buffers and list of offset for each attribute in that buffer - instanceCount*: int # number of instance - case indexed*: bool - of true: - indexType*: VkIndexType - indexBufferOffset*: int - of false: - discard - -func `$`*(drawable: Drawable): string = - if drawable.indexed: - &"Drawable({drawable.name}, elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, bufferOffsets: {drawable.bufferOffsets}, indexType: {drawable.indexType}, indexBufferOffset: {drawable.indexBufferOffset})" - else: - &"Drawable({drawable.name}, elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, bufferOffsets: {drawable.bufferOffsets})" - -proc draw*(drawable: Drawable, commandBuffer: VkCommandBuffer, vertexBuffers: Table[MemoryPerformanceHint, Buffer], indexBuffer: Buffer, pipeline: VkPipeline) = - debug "Draw ", drawable - - var buffers: seq[VkBuffer] - var offsets: seq[VkDeviceSize] - - - for (name, performanceHint, offset) in drawable.bufferOffsets[pipeline]: - buffers.add vertexBuffers[performanceHint].vk - offsets.add VkDeviceSize(offset) - - commandBuffer.vkCmdBindVertexBuffers( - firstBinding=0'u32, - bindingCount=uint32(buffers.len), - pBuffers=buffers.toCPointer(), - pOffsets=offsets.toCPointer() - ) - if drawable.indexed: - commandBuffer.vkCmdBindIndexBuffer(indexBuffer.vk, VkDeviceSize(drawable.indexBufferOffset), drawable.indexType) - commandBuffer.vkCmdDrawIndexed( - indexCount=uint32(drawable.elementCount), - instanceCount=uint32(drawable.instanceCount), - firstIndex=0, - vertexOffset=0, - firstInstance=0 - ) - else: - commandBuffer.vkCmdDraw( - vertexCount=uint32(drawable.elementCount), - instanceCount=uint32(drawable.instanceCount), - firstVertex=0, - firstInstance=0 - ) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/framebuffer.nim --- a/src/semicongine/vulkan/framebuffer.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -import ../core -import ./device -import ./image - - -type - Framebuffer* = object - device*: Device - vk*: VkFramebuffer - dimension*: Vec2u - -proc createFramebuffer*(device: Device, renderpass: VkRenderPass, attachments: openArray[ImageView], dimension: Vec2u): Framebuffer = - assert device.vk.valid - assert renderpass.valid - - result.device = device - result.dimension = dimension - - var theattachments: seq[VkImageView] - for a in attachments: - assert a.vk.valid - theattachments.add a.vk - var framebufferInfo = VkFramebufferCreateInfo( - sType: VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - renderPass: renderpass, - attachmentCount: uint32(theattachments.len), - pAttachments: theattachments.toCPointer, - width: dimension[0], - height: dimension[1], - layers: 1, - ) - checkVkResult device.vk.vkCreateFramebuffer(addr(framebufferInfo), nil, addr(result.vk)) - -proc destroy*(framebuffer: var Framebuffer) = - assert framebuffer.device.vk.valid - assert framebuffer.vk.valid - framebuffer.device.vk.vkDestroyFramebuffer(framebuffer.vk, nil) - framebuffer.vk.reset diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/image.nim --- a/src/semicongine/vulkan/image.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +0,0 @@ -import std/strformat -import std/tables -import std/logging - -import ../core -import ./device -import ./physicaldevice -import ./buffer -import ./memory -import ./commandbuffer - -type - PixelDepth = 1 .. 4 - VulkanImage* = object - device*: Device - vk*: VkImage - width*: int # pixel - height*: int # pixel - depth*: PixelDepth - format*: VkFormat - usage*: seq[VkImageUsageFlagBits] - case memoryAllocated*: bool - of false: discard - of true: - memory*: DeviceMemory - VulkanSampler* = object - device*: Device - vk*: VkSampler - ImageView* = object - vk*: VkImageView - image*: VulkanImage - VulkanTexture* = object - image*: VulkanImage - imageView*: ImageView - sampler*: VulkanSampler - -const DEPTH_FORMAT_MAP = { - PixelDepth(1): VK_FORMAT_R8_SRGB, - PixelDepth(2): VK_FORMAT_R8G8_SRGB, - PixelDepth(3): VK_FORMAT_R8G8B8_SRGB, - PixelDepth(4): VK_FORMAT_R8G8B8A8_SRGB, -}.toTable - - -proc requirements(image: VulkanImage): MemoryRequirements = - assert image.vk.valid - assert image.device.vk.valid - var req: VkMemoryRequirements - image.device.vk.vkGetImageMemoryRequirements(image.vk, addr req) - result.size = req.size - result.alignment = req.alignment - let memorytypes = image.device.physicaldevice.vk.getMemoryProperties().types - for i in 0 ..< sizeof(req.memoryTypeBits) * 8: - if ((req.memoryTypeBits shr i) and 1) == 1: - result.memoryTypes.add memorytypes[i] - -proc allocateMemory(image: var VulkanImage, requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool) = - assert image.device.vk.valid - assert image.memoryAllocated == false - - let requirements = image.requirements() - let memoryType = requirements.memoryTypes.selectBestMemoryType( - requireMappable=requireMappable, - preferVRAM=preferVRAM, - preferAutoFlush=preferAutoFlush - ) - - debug "Allocating memory for image: ", image.width, "x", image.height, "x", image.depth, ", ", requirements.size, " bytes of type ", memoryType - image = VulkanImage( - device: image.device, - vk: image.vk, - width: image.width, - height: image.height, - depth: image.depth, - format: image.format, - usage: image.usage, - memoryAllocated: true, - memory: image.device.allocate(requirements.size, memoryType), - ) - checkVkResult image.device.vk.vkBindImageMemory(image.vk, image.memory.vk, VkDeviceSize(0)) - -proc transitionImageLayout*(image: VulkanImage, oldLayout, newLayout: VkImageLayout) = - var barrier = VkImageMemoryBarrier( - sType: VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - oldLayout: oldLayout, - newLayout: newLayout, - srcQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED, - dstQueueFamilyIndex: VK_QUEUE_FAMILY_IGNORED, - image: image.vk, - subresourceRange: VkImageSubresourceRange( - aspectMask: toBits [VK_IMAGE_ASPECT_COLOR_BIT], - baseMipLevel: 0, - levelCount: 1, - baseArrayLayer: 0, - layerCount: 1, - ), - ) - var - sourceStage, destinationStage: VkPipelineStageFlagBits - if oldLayout == VK_IMAGE_LAYOUT_UNDEFINED and newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - barrier.srcAccessMask = VkAccessFlags(0) - barrier.dstAccessMask = toBits [VK_ACCESS_TRANSFER_WRITE_BIT] - sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT - destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT - elif oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL and newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - barrier.srcAccessMask = toBits [VK_ACCESS_TRANSFER_WRITE_BIT] - barrier.dstAccessMask = toBits [VK_ACCESS_SHADER_READ_BIT] - sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT - destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT - else: - raise newException(Exception, "Unsupported layout transition!") - - withSingleUseCommandBuffer(image.device, false, commandBuffer): - vkCmdPipelineBarrier( - commandBuffer, - toBits [sourceStage], toBits [destinationStage], - VkDependencyFlags(0), - 0, nil, - 0, nil, - 1, addr barrier - ) - -proc copy*(src: Buffer, dst: VulkanImage) = - assert src.device.vk.valid - assert dst.device.vk.valid - assert src.device == dst.device - assert VK_BUFFER_USAGE_TRANSFER_SRC_BIT in src.usage - assert VK_IMAGE_USAGE_TRANSFER_DST_BIT in dst.usage - - var region = VkBufferImageCopy( - bufferOffset: 0, - bufferRowLength: 0, - bufferImageHeight: 0, - imageSubresource: VkImageSubresourceLayers( - aspectMask: toBits [VK_IMAGE_ASPECT_COLOR_BIT], - mipLevel: 0, - baseArrayLayer: 0, - layerCount: 1, - ), - imageOffset: VkOffset3D(x: 0, y: 0, z: 0), - imageExtent: VkExtent3D(width: uint32(dst.width), height: uint32(dst.height), depth: 1) - ) - withSingleUseCommandBuffer(src.device, true, commandBuffer): - commandBuffer.vkCmdCopyBufferToImage( - src.vk, - dst.vk, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - addr region - ) - -# currently only usable for texture access from shader -proc createImage*(device: Device, width, height: int, depth: PixelDepth, data: pointer): VulkanImage = - assert device.vk.valid - assert width > 0 - assert height > 0 - assert depth != 2 - assert data != nil - - let size = width * height * depth - result.device = device - result.width = width - result.height = height - result.depth = depth - result.format = DEPTH_FORMAT_MAP[depth] - result.usage = @[VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT] - - var imageInfo = VkImageCreateInfo( - sType: VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - imageType: VK_IMAGE_TYPE_2D, - extent: VkExtent3D(width: uint32(width), height: uint32(height), depth: 1), - mipLevels: 1, - arrayLayers: 1, - format: result.format, - tiling: VK_IMAGE_TILING_OPTIMAL, - initialLayout: VK_IMAGE_LAYOUT_UNDEFINED, - usage: toBits result.usage, - sharingMode: VK_SHARING_MODE_EXCLUSIVE, - samples: VK_SAMPLE_COUNT_1_BIT, - ) - checkVkResult device.vk.vkCreateImage(addr imageInfo, nil, addr result.vk) - result.allocateMemory(requireMappable=false, preferVRAM=true, preferAutoFlush=false) - result.transitionImageLayout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) - - var stagingBuffer = device.createBuffer(size=size, usage=[VK_BUFFER_USAGE_TRANSFER_SRC_BIT], requireMappable=true, preferVRAM=false, preferAutoFlush=true) - stagingBuffer.setData(src=data, size=size) - stagingBuffer.copy(result) - result.transitionImageLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - stagingBuffer.destroy() - -proc destroy*(image: var VulkanImage) = - assert image.device.vk.valid - assert image.vk.valid - image.device.vk.vkDestroyImage(image.vk, nil) - if image.memoryAllocated: - assert image.memory.vk.valid - image.memory.free - image = VulkanImage( - device: image.device, - vk: image.vk, - width: image.width, - height: image.height, - depth: image.depth, - format: image.format, - usage: image.usage, - memoryAllocated: false, - ) - image.vk.reset - -proc createSampler*(device: Device, sampler: Sampler): VulkanSampler = - assert device.vk.valid - var samplerInfo = VkSamplerCreateInfo( - sType: VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - magFilter: sampler.magnification, - minFilter: sampler.minification, - addressModeU: sampler.wrapModeS, - addressModeV: sampler.wrapModeT, - addressModeW: VK_SAMPLER_ADDRESS_MODE_REPEAT, - anisotropyEnable: device.enabledFeatures.samplerAnisotropy, - maxAnisotropy: device.physicalDevice.properties.limits.maxSamplerAnisotropy, - borderColor: VK_BORDER_COLOR_INT_OPAQUE_BLACK, - unnormalizedCoordinates: VK_FALSE, - compareEnable: VK_FALSE, - compareOp: VK_COMPARE_OP_ALWAYS, - mipmapMode: VK_SAMPLER_MIPMAP_MODE_LINEAR, - mipLodBias: 0, - minLod: 0, - maxLod: 0, - ) - result.device = device - checkVkResult device.vk.vkCreateSampler(addr samplerInfo, nil, addr result.vk) - -proc destroy*(sampler: var VulkanSampler) = - assert sampler.device.vk.valid - assert sampler.vk.valid - sampler.device.vk.vkDestroySampler(sampler.vk, nil) - sampler.vk.reset - -proc createImageView*( - image: VulkanImage, - imageviewtype=VK_IMAGE_VIEW_TYPE_2D, - baseMipLevel=0'u32, - levelCount=1'u32, - baseArrayLayer=0'u32, - layerCount=1'u32 -): ImageView = - assert image.device.vk.valid - assert image.vk.valid - - var createInfo = VkImageViewCreateInfo( - sType: VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - image: image.vk, - viewType: imageviewtype, - format: image.format, - components: VkComponentMapping( - r: VK_COMPONENT_SWIZZLE_IDENTITY, - g: VK_COMPONENT_SWIZZLE_IDENTITY, - b: VK_COMPONENT_SWIZZLE_IDENTITY, - a: VK_COMPONENT_SWIZZLE_IDENTITY, - ), - subresourceRange: VkImageSubresourceRange( - aspectMask: VkImageAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT), - baseMipLevel: baseMipLevel, - levelCount: levelCount, - baseArrayLayer: baseArrayLayer, - layerCount: layerCount, - ), - ) - result.image = image - checkVkResult image.device.vk.vkCreateImageView(addr(createInfo), nil, addr(result.vk)) - -proc destroy*(imageview: var ImageView) = - assert imageview.image.device.vk.valid - assert imageview.vk.valid - imageview.image.device.vk.vkDestroyImageView(imageview.vk, nil) - imageview.vk.reset() - -func `$`*(texture: VulkanTexture): string = - &"VulkanTexture({texture.image.width}x{texture.image.height})" - - -proc uploadTexture*(device: Device, texture: Texture): VulkanTexture = - assert device.vk.valid - result.image = createImage(device=device, width=texture.image.width, height=texture.image.height, depth=4, data=addr texture.image.imagedata[0][0]) - result.imageView = result.image.createImageView() - result.sampler = result.image.device.createSampler(texture.sampler) - -proc destroy*(texture: var VulkanTexture) = - texture.image.destroy() - texture.imageView.destroy() - texture.sampler.destroy() diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/instance.nim --- a/src/semicongine/vulkan/instance.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -import std/strformat -import std/tables -import std/sequtils -import std/logging - -import ../core - -import ../platform/vulkanExtensions -import ../platform/window -import ../platform/surface - -type - Instance* = object - vk*: VkInstance - window*: NativeWindow - surface*: VkSurfaceKHR - Debugger* = object - instance*: Instance - messenger*: VkDebugUtilsMessengerEXT - DebugCallback* = proc ( - messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, - messageTypes: VkDebugUtilsMessageTypeFlagsEXT, - pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT, - userData: pointer - ): VkBool32 {.cdecl.} - -proc getInstanceExtensions*(): seq[string] = - var extensionCount: uint32 - checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), nil) - if extensionCount > 0: - var extensions = newSeq[VkExtensionProperties](extensionCount) - checkVkResult vkEnumerateInstanceExtensionProperties(nil, addr(extensionCount), extensions.toCPointer) - for extension in extensions: - result.add(cleanString(extension.extensionName)) - -proc getLayers*(): seq[string] = - var n_layers: uint32 - checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), nil) - if n_layers > 0: - var layers = newSeq[VkLayerProperties](n_layers) - checkVkResult vkEnumerateInstanceLayerProperties(addr(n_layers), layers.toCPointer) - for layer in layers: - result.add(cleanString(layer.layerName)) - -proc createInstance*( - window: NativeWindow, - vulkanVersion: uint32, - instanceExtensions: seq[string], - layers: seq[string], - name = "defaultVulkanInstance", - engine = "defaultEngine", -): Instance = - - let requiredExtensions = REQUIRED_PLATFORM_EXTENSIONS & @["VK_KHR_surface"] & instanceExtensions - for i in requiredExtensions: - assert i in getInstanceExtensions(), $i - var availableLayers: seq[string] - for i in layers: - if i in getLayers(): - availableLayers.add i - debug "Enabled layers: " & $availableLayers - var - layersC = allocCStringArray(availableLayers) - instanceExtensionsC = allocCStringArray(requiredExtensions) - appinfo = VkApplicationInfo( - sType: VK_STRUCTURE_TYPE_APPLICATION_INFO, - pApplicationName: name, - pEngineName: engine, - apiVersion: vulkanVersion, - ) - createinfo = VkInstanceCreateInfo( - sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - pApplicationInfo: addr(appinfo), - enabledLayerCount: availableLayers.len.uint32, - ppEnabledLayerNames: layersC, - enabledExtensionCount: requiredExtensions.len.uint32, - ppEnabledExtensionNames: instanceExtensionsC - ) - checkVkResult vkCreateInstance(addr(createinfo), nil, addr(result.vk)) - result.vk.loadVulkan() - deallocCStringArray(layersC) - deallocCStringArray(instanceExtensionsC) - for extension in requiredExtensions: - result.vk.loadExtension($extension) - result.surface = result.vk.createNativeSurface(window) - -proc destroy*(instance: var Instance) = - assert instance.vk.valid - assert instance.surface.valid - # needs to happen after window is trashed as the driver might have a hook registered for the window destruction - instance.vk.vkDestroySurfaceKHR(instance.surface, nil) - instance.surface.reset() - instance.vk.vkDestroyInstance(nil) - instance.vk.reset() - -const LEVEL_MAPPING = { - VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: lvlDebug, - VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: lvlInfo, - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: lvlWarn, - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: lvlError, -}.toTable - -proc defaultDebugCallback( - messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, - messageTypes: VkDebugUtilsMessageTypeFlagsEXT, - pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT, - userData: pointer -): VkBool32 {.cdecl.} = - - log LEVEL_MAPPING[messageSeverity], &"{toEnums messageTypes}: {pCallbackData.pMessage}" - if messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: - echo getStackTrace() - quit() - return false - -proc createDebugMessenger*( - instance: Instance, - severityLevels: openArray[VkDebugUtilsMessageSeverityFlagBitsEXT] = @[], - types: openArray[VkDebugUtilsMessageTypeFlagBitsEXT] = @[], - callback: DebugCallback=defaultDebugCallback -): Debugger = - assert instance.vk.valid - result.instance = instance - var severityLevelBits = VkDebugUtilsMessageSeverityFlagBitsEXT.items.toSeq.toBits - var typeBits = VkDebugUtilsMessageTypeFlagBitsEXT.items.toSeq.toBits - if severityLevels.len > 0: - severityLevelBits = toBits severityLevels - if types.len > 0: - typeBits = toBits types - var createInfo = VkDebugUtilsMessengerCreateInfoEXT( - sType: VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - messageSeverity: severityLevelBits, - messageType: typeBits, - pfnUserCallback: callback, - pUserData: nil, - ) - checkVkResult instance.vk.vkCreateDebugUtilsMessengerEXT(addr(createInfo), nil, addr(result.messenger)) - -proc destroy*(debugger: var Debugger) = - assert debugger.messenger.valid - assert debugger.instance.vk.valid - debugger.instance.vk.vkDestroyDebugUtilsMessengerEXT(debugger.messenger, nil) - debugger.messenger.reset() diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/memory.nim --- a/src/semicongine/vulkan/memory.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -import std/strformat - -import ../core -import ./device - -type - MemoryHeap = object - size*: uint64 - flags*: seq[VkMemoryHeapFlagBits] - index*: uint32 - MemoryType* = object - heap*: MemoryHeap - flags*: seq[VkMemoryPropertyFlagBits] - index*: uint32 - PhyscialDeviceMemoryProperties = object - heaps*: seq[MemoryHeap] - types*: seq[MemoryType] - DeviceMemory* = object - device*: Device - vk*: VkDeviceMemory - size*: uint64 - memoryType*: MemoryType - case canMap*: bool - of false: discard - of true: data*: pointer - needsFlushing*: bool - MemoryRequirements* = object - size*: uint64 - alignment*: uint64 - memoryTypes*: seq[MemoryType] - -func `$`*(memoryType: MemoryType): string = - &"Memorytype {memoryType.flags} (heap size: {memoryType.heap.size}, heap flags: {memoryType.heap.flags})" - -proc selectBestMemoryType*(types: seq[MemoryType], requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool): MemoryType = - # todo: we assume there is always at least one memory type that is mappable - assert types.len > 0 - var highestRating = 0'f - result = types[0] - for t in types: - var rating = float(t.heap.size) / 1_000_000'f # select biggest heap if all else equal - if requireMappable and VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in t.flags: - rating += 1000 - if preferVRAM and VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT in t.flags: - rating += 500 - if preferAutoFlush and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in t.flags: - rating += 100 - if rating > highestRating: - highestRating = rating - result = t - -proc getMemoryProperties*(physicalDevice: VkPhysicalDevice): PhyscialDeviceMemoryProperties = - var physicalProperties: VkPhysicalDeviceMemoryProperties - vkGetPhysicalDeviceMemoryProperties(physicalDevice, addr physicalProperties) - for i in 0 ..< physicalProperties.memoryHeapCount: - result.heaps.add MemoryHeap( - size: physicalProperties.memoryHeaps[i].size, - flags: toEnums(physicalProperties.memoryHeaps[i].flags), - index: i, - ) - for i in 0 ..< physicalProperties.memoryTypeCount: - result.types.add MemoryType( - heap: result.heaps[physicalProperties.memoryTypes[i].heapIndex], - flags: toEnums(physicalProperties.memoryTypes[i].propertyFlags), - index: i, - ) - -proc allocate*(device: Device, size: uint64, memoryType: MemoryType): DeviceMemory = - assert device.vk.valid - assert size > 0 - result = DeviceMemory( - device: device, - size: size, - memoryType: memoryType, - canMap: VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in memoryType.flags, - needsFlushing: not (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in memoryType.flags), - ) - - var allocationInfo = VkMemoryAllocateInfo( - sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - allocationSize: size, - memoryTypeIndex: result.memoryType.index, - ) - - checkVkResult vkAllocateMemory( - device.vk, - addr allocationInfo, - nil, - addr result.vk - ) - - if result.canMap: - checkVkResult result.device.vk.vkMapMemory( - memory=result.vk, - offset=VkDeviceSize(0), - size=VkDeviceSize(result.size), - flags=VkMemoryMapFlags(0), # unused up to Vulkan 1.3 - ppData=addr(result.data) - ) - -# flush host -> device -proc flush*(memory: DeviceMemory, offset=0'u64, size=0'u64) = - assert memory.device.vk.valid - assert memory.vk.valid - assert memory.needsFlushing - - var actualSize = size - if actualSize == 0: - actualSize = memory.size - var flushrange = VkMappedMemoryRange( - sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - memory: memory.vk, - offset: VkDeviceSize(offset), - size: VkDeviceSize(size) - ) - checkVkResult memory.device.vk.vkFlushMappedMemoryRanges(memoryRangeCount=1, pMemoryRanges=addr(flushrange)) - -# flush device -> host -proc invalidate*(memory: DeviceMemory, offset=0'u64, size=0'u64) = - assert memory.device.vk.valid - assert memory.vk.valid - assert memory.needsFlushing - - var actualSize = size - if actualSize == 0: - actualSize = memory.size - var flushrange = VkMappedMemoryRange( - sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - memory: memory.vk, - offset: VkDeviceSize(offset), - size: VkDeviceSize(size) - ) - checkVkResult memory.device.vk.vkInvalidateMappedMemoryRanges(memoryRangeCount=1, pMemoryRanges=addr(flushrange)) - -proc free*(memory: var DeviceMemory) = - assert memory.device.vk.valid - assert memory.vk.valid - - memory.device.vk.vkFreeMemory(memory.vk, nil) - memory.vk.reset diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/physicaldevice.nim --- a/src/semicongine/vulkan/physicaldevice.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -from std/enumerate import enumerate -import std/tables -import std/sequtils - -import ../core -import ./instance - -type - PhysicalDevice* = object - vk*: VkPhysicalDevice - name*: string - devicetype*: VkPhysicalDeviceType - surface*: VkSurfaceKHR - properties*: VkPhysicalDeviceProperties - features*: VkPhysicalDeviceFeatures2 - QueueFamily* = object - device: PhysicalDevice - properties*: VkQueueFamilyProperties - index*: uint32 - flags*: seq[VkQueueFlagBits] - -func `$`*(device: PhysicalDevice): string = - "Physical device: vk=" & $device.vk & ", name=" & $device.name & ", devicetype=" & $device.devicetype - -proc getPhysicalDevices*(instance: Instance): seq[PhysicalDevice] = - assert instance.vk.valid - assert instance.surface.valid - var nDevices: uint32 - checkVkResult vkEnumeratePhysicalDevices(instance.vk, addr(nDevices), nil) - var devices = newSeq[VkPhysicalDevice](nDevices) - checkVkResult vkEnumeratePhysicalDevices(instance.vk, addr(nDevices), devices.toCPointer) - for i in 0 ..< nDevices: - var device = PhysicalDevice(vk: devices[i], surface: instance.surface) - device.vk.vkGetPhysicalDeviceProperties(addr device.properties) - device.features.stype = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 - device.vk.vkGetPhysicalDeviceFeatures2(addr device.features) - device.name = device.properties.deviceName.cleanString() - device.devicetype = device.properties.deviceType - result.add device - -proc getExtensions*(device: PhysicalDevice): seq[string] = - assert device.vk.valid - var extensionCount: uint32 - checkVkResult vkEnumerateDeviceExtensionProperties(device.vk, nil, addr(extensionCount), nil) - if extensionCount > 0: - var extensions = newSeq[VkExtensionProperties](extensionCount) - checkVkResult vkEnumerateDeviceExtensionProperties(device.vk, nil, addr(extensionCount), extensions.toCPointer) - for extension in extensions: - result.add(cleanString(extension.extensionName)) - -proc getSurfaceCapabilities*(device: PhysicalDevice): VkSurfaceCapabilitiesKHR = - assert device.vk.valid - assert device.surface.valid - checkVkResult device.vk.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device.surface, addr(result)) - -proc getSurfaceFormats*(device: PhysicalDevice): seq[VkSurfaceFormatKHR] = - assert device.vk.valid - assert device.surface.valid - var n_formats: uint32 - checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device.vk, device.surface, addr(n_formats), nil) - result = newSeq[VkSurfaceFormatKHR](n_formats) - checkVkResult vkGetPhysicalDeviceSurfaceFormatsKHR(device.vk, device.surface, addr(n_formats), result.toCPointer) - -func filterSurfaceFormat*( - formats: seq[VkSurfaceFormatKHR], - imageFormat = VK_FORMAT_B8G8R8A8_SRGB, - colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR -): VkSurfaceFormatKHR = - for format in formats: - if format.format == imageFormat and format.colorSpace == colorSpace: - return format - -proc filterSurfaceFormat*(device: PhysicalDevice): VkSurfaceFormatKHR = - assert device.vk.valid - assert device.surface.valid - device.getSurfaceFormats().filterSurfaceFormat() - -proc getSurfacePresentModes*(device: PhysicalDevice): seq[VkPresentModeKHR] = - assert device.vk.valid - assert device.surface.valid - var n_modes: uint32 - checkVkResult vkGetPhysicalDeviceSurfacePresentModesKHR(device.vk, device.surface, addr(n_modes), nil) - result = newSeq[VkPresentModeKHR](n_modes) - checkVkResult vkGetPhysicalDeviceSurfacePresentModesKHR(device.vk, device.surface, addr(n_modes), result.toCPointer) - -proc getQueueFamilies*(device: PhysicalDevice): seq[QueueFamily] = - assert device.vk.valid - var nQueuefamilies: uint32 - vkGetPhysicalDeviceQueueFamilyProperties(device.vk, addr nQueuefamilies, nil) - var queuFamilies = newSeq[VkQueueFamilyProperties](nQueuefamilies) - vkGetPhysicalDeviceQueueFamilyProperties(device.vk, addr nQueuefamilies , queuFamilies.toCPointer) - for i in 0 ..< nQueuefamilies: - result.add QueueFamily( - device: device, - properties: queuFamilies[i], - index: i, - flags: queuFamilies[i].queueFlags.toEnums, - ) - -proc canDoGraphics*(family: QueueFamily): bool = - VK_QUEUE_GRAPHICS_BIT in family.flags - -proc canDoPresentation*(family: QueueFamily, surface: VkSurfaceKHR): bool = - assert surface.valid - var presentation = VkBool32(false) - checkVkResult vkGetPhysicalDeviceSurfaceSupportKHR(family.device.vk, family.index, surface, addr presentation) - return bool(presentation) - -proc canDoTransfer*(family: QueueFamily): bool = - VK_QUEUE_TRANSFER_BIT in family.flags - -proc filterForGraphicsPresentationQueues*(device: PhysicalDevice): seq[QueueFamily] = - var canDoGraphics = false - var canDoPresentation = false - var queues: Table[uint32, QueueFamily] - for family in device.getQueueFamilies(): - if family.canDoGraphics: - queues[family.index] = family - canDoGraphics = true - if family.canDoPresentation(device.surface): - queues[family.index] = family - canDoPresentation = true - if canDoGraphics and canDoPresentation: - return queues.values.toSeq - -proc filterGraphics(families: seq[QueueFamily]): seq[QueueFamily] = - for family in families: - if family.canDoGraphics: - result.add family - -proc filterPresentation(families: seq[QueueFamily], surface: VkSurfaceKHR): seq[QueueFamily] = - assert surface.valid - for family in families: - if family.canDoPresentation(surface): - result.add family - -proc rateGraphics*(device: PhysicalDevice): float = - assert device.vk.valid - assert device.surface.valid - if device.getQueueFamilies().filterGraphics().filterPresentation(device.surface).len == 0: - return -1 - if not ("VK_KHR_swapchain" in device.getExtensions()): - return -1 - const deviceTypeMap = [ - VK_PHYSICAL_DEVICE_TYPE_OTHER, - VK_PHYSICAL_DEVICE_TYPE_CPU, - VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU, - VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, - VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, - ] - for (i, devicetype) in enumerate(deviceTypeMap): - if device.devicetype == devicetype: - result = float(i) - -proc filterBestGraphics*(devices: seq[PhysicalDevice]): PhysicalDevice = - var bestVal = -1'f - for device in devices: - assert device.vk.valid - assert device.surface.valid - let rating = device.rateGraphics() - if rating > bestVal: - bestVal = rating - result = device - assert bestVal >= 0 diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/pipeline.nim --- a/src/semicongine/vulkan/pipeline.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,203 +0,0 @@ -import std/tables -import std/sequtils -import std/strformat - -import ../core -import ./device -import ./descriptor -import ./shader -import ./buffer -import ./image - -type - ShaderPipeline* = object - device*: Device - vk*: VkPipeline - layout*: VkPipelineLayout - shaderConfiguration*: ShaderConfiguration - shaderModules*: (ShaderModule, ShaderModule) - descriptorSetLayout*: DescriptorSetLayout - -func inputs*(pipeline: ShaderPipeline): seq[ShaderAttribute] = - pipeline.shaderConfiguration.inputs - -func uniforms*(pipeline: ShaderPipeline): seq[ShaderAttribute] = - pipeline.shaderConfiguration.uniforms - -func samplers*(pipeline: ShaderPipeline): seq[ShaderAttribute] = - pipeline.shaderConfiguration.samplers - -proc setupDescriptors*(pipeline: ShaderPipeline, descriptorPool: DescriptorPool, buffers: seq[Buffer], textures: var Table[string, seq[VulkanTexture]], inFlightFrames: int, emptyTexture: VulkanTexture): seq[DescriptorSet] = - assert pipeline.vk.valid - assert buffers.len == 0 or buffers.len == inFlightFrames # need to guard against this in case we have no uniforms, then we also create no buffers - - result = descriptorPool.allocateDescriptorSet(pipeline.descriptorSetLayout, inFlightFrames) - - for i in 0 ..< inFlightFrames: - var offset = 0 - # first descriptor is always uniform for globals, match should be better somehow - for descriptor in result[i].layout.descriptors.mitems: - if descriptor.thetype == Uniform and buffers.len > 0: - let size = descriptor.size - descriptor.buffer = buffers[i] - descriptor.offset = offset - descriptor.size = size - offset += size - elif descriptor.thetype == ImageSampler: - if not (descriptor.name in textures): - raise newException(Exception, &"Missing shader texture in scene: {descriptor.name}, available are {textures.keys.toSeq}") - - for textureIndex in 0 ..< int(descriptor.count): - if textureIndex < textures[descriptor.name].len: - descriptor.imageviews.add textures[descriptor.name][textureIndex].imageView - descriptor.samplers.add textures[descriptor.name][textureIndex].sampler - else: - descriptor.imageviews.add emptyTexture.imageView - descriptor.samplers.add emptyTexture.sampler - -proc createPipeline*(device: Device, renderPass: VkRenderPass, shaderConfiguration: ShaderConfiguration, inFlightFrames: int, subpass = 0'u32, backFaceCulling=true): ShaderPipeline = - assert renderPass.valid - assert device.vk.valid - - result.device = device - result.shaderModules = device.createShaderModules(shaderConfiguration) - result.shaderConfiguration = shaderConfiguration - - var descriptors: seq[Descriptor] - if result.shaderConfiguration.uniforms.len > 0: - descriptors.add Descriptor( - name: "Uniforms", - thetype: Uniform, - count: 1, - stages: @[VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT], - size: result.shaderConfiguration.uniforms.size(), - ) - for sampler in result.shaderConfiguration.samplers: - descriptors.add Descriptor( - name: sampler.name, - thetype: ImageSampler, - count: (if sampler.arrayCount == 0: 1 else: sampler.arrayCount), - stages: @[VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT], - ) - result.descriptorSetLayout = device.createDescriptorSetLayout(descriptors) - - # TODO: Push constants - # var pushConstant = VkPushConstantRange( - # stageFlags: toBits shaderStage, - # offset: 0, - # size: 0, - # ) - var descriptorSetLayouts: seq[VkDescriptorSetLayout] = @[result.descriptorSetLayout.vk] - # var pushConstants: seq[VkPushConstantRange] = @[pushConstant] - var pipelineLayoutInfo = VkPipelineLayoutCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - setLayoutCount: uint32(descriptorSetLayouts.len), - pSetLayouts: descriptorSetLayouts.toCPointer, - # pushConstantRangeCount: uint32(pushConstants.len), - # pPushConstantRanges: pushConstants.toCPointer, - ) - checkVkResult vkCreatePipelineLayout(device.vk, addr(pipelineLayoutInfo), nil, addr(result.layout)) - - var - bindings: seq[VkVertexInputBindingDescription] - attributes: seq[VkVertexInputAttributeDescription] - vertexInputInfo = result.shaderConfiguration.getVertexInputInfo(bindings, attributes) - inputAssembly = VkPipelineInputAssemblyStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - topology: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - primitiveRestartEnable: VK_FALSE, - ) - viewportState = VkPipelineViewportStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - viewportCount: 1, - scissorCount: 1, - ) - rasterizer = VkPipelineRasterizationStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - depthClampEnable: VK_FALSE, - rasterizerDiscardEnable: VK_FALSE, - polygonMode: VK_POLYGON_MODE_FILL, - lineWidth: 1.0, - cullMode: if backFaceCulling: toBits [VK_CULL_MODE_BACK_BIT] else: VkCullModeFlags(0), - frontFace: VK_FRONT_FACE_CLOCKWISE, - depthBiasEnable: VK_FALSE, - depthBiasConstantFactor: 0.0, - depthBiasClamp: 0.0, - depthBiasSlopeFactor: 0.0, - ) - multisampling = VkPipelineMultisampleStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - sampleShadingEnable: VK_FALSE, - rasterizationSamples: VK_SAMPLE_COUNT_1_BIT, - minSampleShading: 1.0, - pSampleMask: nil, - alphaToCoverageEnable: VK_FALSE, - alphaToOneEnable: VK_FALSE, - ) - colorBlendAttachment = VkPipelineColorBlendAttachmentState( - colorWriteMask: toBits [VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, VK_COLOR_COMPONENT_A_BIT], - blendEnable: VK_TRUE, - srcColorBlendFactor: VK_BLEND_FACTOR_SRC_ALPHA, - dstColorBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - colorBlendOp: VK_BLEND_OP_ADD, - srcAlphaBlendFactor: VK_BLEND_FACTOR_ONE, - dstAlphaBlendFactor: VK_BLEND_FACTOR_ZERO, - alphaBlendOp: VK_BLEND_OP_ADD, - ) - colorBlending = VkPipelineColorBlendStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - logicOpEnable: false, - attachmentCount: 1, - pAttachments: addr(colorBlendAttachment), - ) - dynamicStates = @[VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR] - dynamicState = VkPipelineDynamicStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - dynamicStateCount: uint32(dynamicStates.len), - pDynamicStates: dynamicStates.toCPointer, - ) - stages = @[result.shaderModules[0].getPipelineInfo(), result.shaderModules[1].getPipelineInfo()] - createInfo = VkGraphicsPipelineCreateInfo( - sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - stageCount: uint32(stages.len), - pStages: stages.toCPointer, - pVertexInputState: addr(vertexInputInfo), - pInputAssemblyState: addr(inputAssembly), - pViewportState: addr(viewportState), - pRasterizationState: addr(rasterizer), - pMultisampleState: addr(multisampling), - pDepthStencilState: nil, - pColorBlendState: addr(colorBlending), - pDynamicState: addr(dynamicState), - layout: result.layout, - renderPass: renderPass, - subpass: subpass, - basePipelineHandle: VkPipeline(0), - basePipelineIndex: -1, - ) - checkVkResult vkCreateGraphicsPipelines( - device.vk, - VkPipelineCache(0), - 1, - addr(createInfo), - nil, - addr(result.vk) - ) - - discard result.uniforms # just for assertion - - -proc destroy*(pipeline: var ShaderPipeline) = - assert pipeline.device.vk.valid - assert pipeline.vk.valid - assert pipeline.layout.valid - assert pipeline.descriptorSetLayout.vk.valid - - pipeline.shaderModules[0].destroy() - pipeline.shaderModules[1].destroy() - pipeline.descriptorSetLayout.destroy() - pipeline.device.vk.vkDestroyPipelineLayout(pipeline.layout, nil) - pipeline.device.vk.vkDestroyPipeline(pipeline.vk, nil) - pipeline.descriptorSetLayout.reset() - pipeline.layout.reset() - pipeline.vk.reset() diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/android.nim --- a/src/semicongine/vulkan/platform/android.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -type - VkAndroidSurfaceCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkAndroidSurfaceCreateFlagsKHR - window*: ptr ANativeWindow - VkNativeBufferUsage2ANDROID* = object - consumer*: uint64 - producer*: uint64 - VkNativeBufferANDROID* = object - sType*: VkStructureType - pNext*: pointer - handle*: pointer - stride*: cint - format*: cint - usage*: cint - usage2*: VkNativeBufferUsage2ANDROID - VkSwapchainImageCreateInfoANDROID* = object - sType*: VkStructureType - pNext*: pointer - usage*: VkSwapchainImageUsageFlagsANDROID - VkPhysicalDevicePresentationPropertiesANDROID* = object - sType*: VkStructureType - pNext*: pointer - sharedImage*: VkBool32 - VkImportAndroidHardwareBufferInfoANDROID* = object - sType*: VkStructureType - pNext*: pointer - buffer*: ptr AHardwareBuffer - VkAndroidHardwareBufferUsageANDROID* = object - sType*: VkStructureType - pNext*: pointer - androidHardwareBufferUsage*: uint64 - VkAndroidHardwareBufferPropertiesANDROID* = object - sType*: VkStructureType - pNext*: pointer - allocationSize*: VkDeviceSize - memoryTypeBits*: uint32 - VkMemoryGetAndroidHardwareBufferInfoANDROID* = object - sType*: VkStructureType - pNext*: pointer - memory*: VkDeviceMemory - VkAndroidHardwareBufferFormatPropertiesANDROID* = object - sType*: VkStructureType - pNext*: pointer - format*: VkFormat - externalFormat*: uint64 - formatFeatures*: VkFormatFeatureFlags - samplerYcbcrConversionComponents*: VkComponentMapping - suggestedYcbcrModel*: VkSamplerYcbcrModelConversion - suggestedYcbcrRange*: VkSamplerYcbcrRange - suggestedXChromaOffset*: VkChromaLocation - suggestedYChromaOffset*: VkChromaLocation - VkExternalFormatANDROID* = object - sType*: VkStructureType - pNext*: pointer - externalFormat*: uint64 - VkAndroidHardwareBufferFormatProperties2ANDROID* = object - sType*: VkStructureType - pNext*: pointer - format*: VkFormat - externalFormat*: uint64 - formatFeatures*: VkFormatFeatureFlags2 - samplerYcbcrConversionComponents*: VkComponentMapping - suggestedYcbcrModel*: VkSamplerYcbcrModelConversion - suggestedYcbcrRange*: VkSamplerYcbcrRange - suggestedXChromaOffset*: VkChromaLocation - suggestedYChromaOffset*: VkChromaLocation -# extension VK_ANDROID_external_memory_android_hardware_buffer -var - vkGetAndroidHardwareBufferPropertiesANDROID*: proc(device: VkDevice, buffer: ptr AHardwareBuffer, pProperties: ptr VkAndroidHardwareBufferPropertiesANDROID): VkResult {.stdcall.} - vkGetMemoryAndroidHardwareBufferANDROID*: proc(device: VkDevice, pInfo: ptr VkMemoryGetAndroidHardwareBufferInfoANDROID, pBuffer: ptr ptr AHardwareBuffer): VkResult {.stdcall.} -proc loadVK_ANDROID_external_memory_android_hardware_buffer*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_1(instance) - loadVK_EXT_queue_family_foreign(instance) - loadVK_VERSION_1_1(instance) - vkGetAndroidHardwareBufferPropertiesANDROID = cast[proc(device: VkDevice, buffer: ptr AHardwareBuffer, pProperties: ptr VkAndroidHardwareBufferPropertiesANDROID): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetAndroidHardwareBufferPropertiesANDROID")) - vkGetMemoryAndroidHardwareBufferANDROID = cast[proc(device: VkDevice, pInfo: ptr VkMemoryGetAndroidHardwareBufferInfoANDROID, pBuffer: ptr ptr AHardwareBuffer): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryAndroidHardwareBufferANDROID")) - -# extension VK_KHR_android_surface -var - vkCreateAndroidSurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkAndroidSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} -proc loadVK_KHR_android_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateAndroidSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkAndroidSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateAndroidSurfaceKHR")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/directfb.nim --- a/src/semicongine/vulkan/platform/directfb.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -type - VkDirectFBSurfaceCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkDirectFBSurfaceCreateFlagsEXT - dfb*: ptr IDirectFB - surface*: ptr IDirectFBSurface - IDirectFB *{.header: "directfb.h".} = object - IDirectFBSurface *{.header: "directfb.h".} = object -# extension VK_EXT_directfb_surface -var - vkCreateDirectFBSurfaceEXT*: proc(instance: VkInstance, pCreateInfo: ptr VkDirectFBSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceDirectFBPresentationSupportEXT*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, dfb: ptr IDirectFB): VkBool32 {.stdcall.} -proc loadVK_EXT_directfb_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateDirectFBSurfaceEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkDirectFBSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateDirectFBSurfaceEXT")) - vkGetPhysicalDeviceDirectFBPresentationSupportEXT = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, dfb: ptr IDirectFB): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDirectFBPresentationSupportEXT")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/fuchsia.nim --- a/src/semicongine/vulkan/platform/fuchsia.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -type - VkImagePipeSurfaceCreateInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkImagePipeSurfaceCreateFlagsFUCHSIA - imagePipeHandle*: zx_handle_t - VkImportMemoryZirconHandleInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - handleType*: VkExternalMemoryHandleTypeFlagBits - handle*: zx_handle_t - VkMemoryZirconHandlePropertiesFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - memoryTypeBits*: uint32 - VkMemoryGetZirconHandleInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - memory*: VkDeviceMemory - handleType*: VkExternalMemoryHandleTypeFlagBits - VkImportSemaphoreZirconHandleInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - flags*: VkSemaphoreImportFlags - handleType*: VkExternalSemaphoreHandleTypeFlagBits - zirconHandle*: zx_handle_t - VkSemaphoreGetZirconHandleInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - handleType*: VkExternalSemaphoreHandleTypeFlagBits - VkImportMemoryBufferCollectionFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - collection*: VkBufferCollectionFUCHSIA - index*: uint32 - VkBufferCollectionImageCreateInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - collection*: VkBufferCollectionFUCHSIA - index*: uint32 - VkBufferCollectionBufferCreateInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - collection*: VkBufferCollectionFUCHSIA - index*: uint32 - VkBufferCollectionCreateInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - collectionToken*: zx_handle_t - VkBufferCollectionPropertiesFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - memoryTypeBits*: uint32 - bufferCount*: uint32 - createInfoIndex*: uint32 - sysmemPixelFormat*: uint64 - formatFeatures*: VkFormatFeatureFlags - sysmemColorSpaceIndex*: VkSysmemColorSpaceFUCHSIA - samplerYcbcrConversionComponents*: VkComponentMapping - suggestedYcbcrModel*: VkSamplerYcbcrModelConversion - suggestedYcbcrRange*: VkSamplerYcbcrRange - suggestedXChromaOffset*: VkChromaLocation - suggestedYChromaOffset*: VkChromaLocation - VkBufferConstraintsInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - createInfo*: VkBufferCreateInfo - requiredFormatFeatures*: VkFormatFeatureFlags - bufferCollectionConstraints*: VkBufferCollectionConstraintsInfoFUCHSIA - VkSysmemColorSpaceFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - colorSpace*: uint32 - VkImageFormatConstraintsInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - imageCreateInfo*: VkImageCreateInfo - requiredFormatFeatures*: VkFormatFeatureFlags - flags*: VkImageFormatConstraintsFlagsFUCHSIA - sysmemPixelFormat*: uint64 - colorSpaceCount*: uint32 - pColorSpaces*: ptr VkSysmemColorSpaceFUCHSIA - VkImageConstraintsInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - formatConstraintsCount*: uint32 - pFormatConstraints*: ptr VkImageFormatConstraintsInfoFUCHSIA - bufferCollectionConstraints*: VkBufferCollectionConstraintsInfoFUCHSIA - flags*: VkImageConstraintsInfoFlagsFUCHSIA - VkBufferCollectionConstraintsInfoFUCHSIA* = object - sType*: VkStructureType - pNext*: pointer - minBufferCount*: uint32 - maxBufferCount*: uint32 - minBufferCountForCamping*: uint32 - minBufferCountForDedicatedSlack*: uint32 - minBufferCountForSharedSlack*: uint32 - zx_handle_t *{.header: "zircon/types.h".} = object -# extension VK_FUCHSIA_external_memory -var - vkGetMemoryZirconHandleFUCHSIA*: proc(device: VkDevice, pGetZirconHandleInfo: ptr VkMemoryGetZirconHandleInfoFUCHSIA, pZirconHandle: ptr zx_handle_t): VkResult {.stdcall.} - vkGetMemoryZirconHandlePropertiesFUCHSIA*: proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, zirconHandle: zx_handle_t, pMemoryZirconHandleProperties: ptr VkMemoryZirconHandlePropertiesFUCHSIA): VkResult {.stdcall.} -proc loadVK_FUCHSIA_external_memory*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_1(instance) - vkGetMemoryZirconHandleFUCHSIA = cast[proc(device: VkDevice, pGetZirconHandleInfo: ptr VkMemoryGetZirconHandleInfoFUCHSIA, pZirconHandle: ptr zx_handle_t): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryZirconHandleFUCHSIA")) - vkGetMemoryZirconHandlePropertiesFUCHSIA = cast[proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, zirconHandle: zx_handle_t, pMemoryZirconHandleProperties: ptr VkMemoryZirconHandlePropertiesFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryZirconHandlePropertiesFUCHSIA")) - -# extension VK_FUCHSIA_external_semaphore -var - vkImportSemaphoreZirconHandleFUCHSIA*: proc(device: VkDevice, pImportSemaphoreZirconHandleInfo: ptr VkImportSemaphoreZirconHandleInfoFUCHSIA): VkResult {.stdcall.} - vkGetSemaphoreZirconHandleFUCHSIA*: proc(device: VkDevice, pGetZirconHandleInfo: ptr VkSemaphoreGetZirconHandleInfoFUCHSIA, pZirconHandle: ptr zx_handle_t): VkResult {.stdcall.} -proc loadVK_FUCHSIA_external_semaphore*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_1(instance) - vkImportSemaphoreZirconHandleFUCHSIA = cast[proc(device: VkDevice, pImportSemaphoreZirconHandleInfo: ptr VkImportSemaphoreZirconHandleInfoFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkImportSemaphoreZirconHandleFUCHSIA")) - vkGetSemaphoreZirconHandleFUCHSIA = cast[proc(device: VkDevice, pGetZirconHandleInfo: ptr VkSemaphoreGetZirconHandleInfoFUCHSIA, pZirconHandle: ptr zx_handle_t): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSemaphoreZirconHandleFUCHSIA")) - -# extension VK_FUCHSIA_buffer_collection -var - vkCreateBufferCollectionFUCHSIA*: proc(device: VkDevice, pCreateInfo: ptr VkBufferCollectionCreateInfoFUCHSIA, pAllocator: ptr VkAllocationCallbacks, pCollection: ptr VkBufferCollectionFUCHSIA): VkResult {.stdcall.} - vkSetBufferCollectionImageConstraintsFUCHSIA*: proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pImageConstraintsInfo: ptr VkImageConstraintsInfoFUCHSIA): VkResult {.stdcall.} - vkSetBufferCollectionBufferConstraintsFUCHSIA*: proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pBufferConstraintsInfo: ptr VkBufferConstraintsInfoFUCHSIA): VkResult {.stdcall.} - vkDestroyBufferCollectionFUCHSIA*: proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetBufferCollectionPropertiesFUCHSIA*: proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pProperties: ptr VkBufferCollectionPropertiesFUCHSIA): VkResult {.stdcall.} -proc loadVK_FUCHSIA_buffer_collection*(instance: VkInstance) = - loadVK_FUCHSIA_external_memory(instance) - loadVK_VERSION_1_1(instance) - vkCreateBufferCollectionFUCHSIA = cast[proc(device: VkDevice, pCreateInfo: ptr VkBufferCollectionCreateInfoFUCHSIA, pAllocator: ptr VkAllocationCallbacks, pCollection: ptr VkBufferCollectionFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateBufferCollectionFUCHSIA")) - vkSetBufferCollectionImageConstraintsFUCHSIA = cast[proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pImageConstraintsInfo: ptr VkImageConstraintsInfoFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetBufferCollectionImageConstraintsFUCHSIA")) - vkSetBufferCollectionBufferConstraintsFUCHSIA = cast[proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pBufferConstraintsInfo: ptr VkBufferConstraintsInfoFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkSetBufferCollectionBufferConstraintsFUCHSIA")) - vkDestroyBufferCollectionFUCHSIA = cast[proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyBufferCollectionFUCHSIA")) - vkGetBufferCollectionPropertiesFUCHSIA = cast[proc(device: VkDevice, collection: VkBufferCollectionFUCHSIA, pProperties: ptr VkBufferCollectionPropertiesFUCHSIA): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetBufferCollectionPropertiesFUCHSIA")) - -# extension VK_FUCHSIA_imagepipe_surface -var - vkCreateImagePipeSurfaceFUCHSIA*: proc(instance: VkInstance, pCreateInfo: ptr VkImagePipeSurfaceCreateInfoFUCHSIA, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} -proc loadVK_FUCHSIA_imagepipe_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateImagePipeSurfaceFUCHSIA = cast[proc(instance: VkInstance, pCreateInfo: ptr VkImagePipeSurfaceCreateInfoFUCHSIA, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateImagePipeSurfaceFUCHSIA")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/ggp.nim --- a/src/semicongine/vulkan/platform/ggp.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -type - VkStreamDescriptorSurfaceCreateInfoGGP* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkStreamDescriptorSurfaceCreateFlagsGGP - streamDescriptor*: GgpStreamDescriptor - VkPresentFrameTokenGGP* = object - sType*: VkStructureType - pNext*: pointer - frameToken*: GgpFrameToken - GgpStreamDescriptor *{.header: "ggp_c/vulkan_types.h".} = object - GgpFrameToken *{.header: "ggp_c/vulkan_types.h".} = object -# extension VK_GGP_stream_descriptor_surface -var - vkCreateStreamDescriptorSurfaceGGP*: proc(instance: VkInstance, pCreateInfo: ptr VkStreamDescriptorSurfaceCreateInfoGGP, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} -proc loadVK_GGP_stream_descriptor_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateStreamDescriptorSurfaceGGP = cast[proc(instance: VkInstance, pCreateInfo: ptr VkStreamDescriptorSurfaceCreateInfoGGP, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateStreamDescriptorSurfaceGGP")) - -proc loadVK_GGP_frame_token*(instance: VkInstance) = - loadVK_KHR_swapchain(instance) - loadVK_GGP_stream_descriptor_surface(instance) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/ios.nim --- a/src/semicongine/vulkan/platform/ios.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -type - VkIOSSurfaceCreateInfoMVK* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkIOSSurfaceCreateFlagsMVK - pView*: pointer -# extension VK_MVK_ios_surface -var - vkCreateIOSSurfaceMVK*: proc(instance: VkInstance, pCreateInfo: ptr VkIOSSurfaceCreateInfoMVK, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} -proc loadVK_MVK_ios_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateIOSSurfaceMVK = cast[proc(instance: VkInstance, pCreateInfo: ptr VkIOSSurfaceCreateInfoMVK, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateIOSSurfaceMVK")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/macos.nim --- a/src/semicongine/vulkan/platform/macos.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -type - VkMacOSSurfaceCreateInfoMVK* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkMacOSSurfaceCreateFlagsMVK - pView*: pointer -# extension VK_MVK_macos_surface -var - vkCreateMacOSSurfaceMVK*: proc(instance: VkInstance, pCreateInfo: ptr VkMacOSSurfaceCreateInfoMVK, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} -proc loadVK_MVK_macos_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateMacOSSurfaceMVK = cast[proc(instance: VkInstance, pCreateInfo: ptr VkMacOSSurfaceCreateInfoMVK, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/metal.nim --- a/src/semicongine/vulkan/platform/metal.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -type - VkMetalSurfaceCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkMetalSurfaceCreateFlagsEXT - pLayer*: ptr CAMetalLayer - VkExportMetalObjectCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - exportObjectType*: VkExportMetalObjectTypeFlagBitsEXT - VkExportMetalObjectsInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - VkExportMetalDeviceInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - mtlDevice*: MTLDevice_id - VkExportMetalCommandQueueInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - queue*: VkQueue - mtlCommandQueue*: MTLCommandQueue_id - VkExportMetalBufferInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - memory*: VkDeviceMemory - mtlBuffer*: MTLBuffer_id - VkImportMetalBufferInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - mtlBuffer*: MTLBuffer_id - VkExportMetalTextureInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - image*: VkImage - imageView*: VkImageView - bufferView*: VkBufferView - plane*: VkImageAspectFlagBits - mtlTexture*: MTLTexture_id - VkImportMetalTextureInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - plane*: VkImageAspectFlagBits - mtlTexture*: MTLTexture_id - VkExportMetalIOSurfaceInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - image*: VkImage - ioSurface*: IOSurfaceRef - VkImportMetalIOSurfaceInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - ioSurface*: IOSurfaceRef - VkExportMetalSharedEventInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - event*: VkEvent - mtlSharedEvent*: MTLSharedEvent_id - VkImportMetalSharedEventInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - mtlSharedEvent*: MTLSharedEvent_id -# extension VK_EXT_metal_objects -var - vkExportMetalObjectsEXT*: proc(device: VkDevice, pMetalObjectsInfo: ptr VkExportMetalObjectsInfoEXT): void {.stdcall.} -proc loadVK_EXT_metal_objects*(instance: VkInstance) = - vkExportMetalObjectsEXT = cast[proc(device: VkDevice, pMetalObjectsInfo: ptr VkExportMetalObjectsInfoEXT): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkExportMetalObjectsEXT")) - -# extension VK_EXT_metal_surface -var - vkCreateMetalSurfaceEXT*: proc(instance: VkInstance, pCreateInfo: ptr VkMetalSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} -proc loadVK_EXT_metal_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateMetalSurfaceEXT = cast[proc(instance: VkInstance, pCreateInfo: ptr VkMetalSurfaceCreateInfoEXT, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/provisional.nim --- a/src/semicongine/vulkan/platform/provisional.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,581 +0,0 @@ -type - VkPhysicalDevicePortabilitySubsetFeaturesKHR* = object - sType*: VkStructureType - pNext*: pointer - constantAlphaColorBlendFactors*: VkBool32 - events*: VkBool32 - imageViewFormatReinterpretation*: VkBool32 - imageViewFormatSwizzle*: VkBool32 - imageView2DOn3DImage*: VkBool32 - multisampleArrayImage*: VkBool32 - mutableComparisonSamplers*: VkBool32 - pointPolygons*: VkBool32 - samplerMipLodBias*: VkBool32 - separateStencilMaskRef*: VkBool32 - shaderSampleRateInterpolationFunctions*: VkBool32 - tessellationIsolines*: VkBool32 - tessellationPointMode*: VkBool32 - triangleFans*: VkBool32 - vertexAttributeAccessBeyondStride*: VkBool32 - VkPhysicalDevicePortabilitySubsetPropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - minVertexInputBindingStrideAlignment*: uint32 - VkQueueFamilyVideoPropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - videoCodecOperations*: VkVideoCodecOperationFlagsKHR - VkQueueFamilyQueryResultStatusPropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - queryResultStatusSupport*: VkBool32 - VkVideoProfileListInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - profileCount*: uint32 - pProfiles*: ptr VkVideoProfileInfoKHR - VkPhysicalDeviceVideoFormatInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - imageUsage*: VkImageUsageFlags - VkVideoFormatPropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - format*: VkFormat - componentMapping*: VkComponentMapping - imageCreateFlags*: VkImageCreateFlags - imageType*: VkImageType - imageTiling*: VkImageTiling - imageUsageFlags*: VkImageUsageFlags - VkVideoProfileInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - videoCodecOperation*: VkVideoCodecOperationFlagBitsKHR - chromaSubsampling*: VkVideoChromaSubsamplingFlagsKHR - lumaBitDepth*: VkVideoComponentBitDepthFlagsKHR - chromaBitDepth*: VkVideoComponentBitDepthFlagsKHR - VkVideoCapabilitiesKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoCapabilityFlagsKHR - minBitstreamBufferOffsetAlignment*: VkDeviceSize - minBitstreamBufferSizeAlignment*: VkDeviceSize - pictureAccessGranularity*: VkExtent2D - minCodedExtent*: VkExtent2D - maxCodedExtent*: VkExtent2D - maxDpbSlots*: uint32 - maxActiveReferencePictures*: uint32 - stdHeaderVersion*: VkExtensionProperties - VkVideoSessionMemoryRequirementsKHR* = object - sType*: VkStructureType - pNext*: pointer - memoryBindIndex*: uint32 - memoryRequirements*: VkMemoryRequirements - VkBindVideoSessionMemoryInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - memoryBindIndex*: uint32 - memory*: VkDeviceMemory - memoryOffset*: VkDeviceSize - memorySize*: VkDeviceSize - VkVideoPictureResourceInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - codedOffset*: VkOffset2D - codedExtent*: VkExtent2D - baseArrayLayer*: uint32 - imageViewBinding*: VkImageView - VkVideoReferenceSlotInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - slotIndex*: int32 - pPictureResource*: ptr VkVideoPictureResourceInfoKHR - VkVideoDecodeCapabilitiesKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoDecodeCapabilityFlagsKHR - VkVideoDecodeUsageInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - videoUsageHints*: VkVideoDecodeUsageFlagsKHR - VkVideoDecodeInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoDecodeFlagsKHR - srcBuffer*: VkBuffer - srcBufferOffset*: VkDeviceSize - srcBufferRange*: VkDeviceSize - dstPictureResource*: VkVideoPictureResourceInfoKHR - pSetupReferenceSlot*: ptr VkVideoReferenceSlotInfoKHR - referenceSlotCount*: uint32 - pReferenceSlots*: ptr VkVideoReferenceSlotInfoKHR - VkVideoDecodeH264ProfileInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - stdProfileIdc*: StdVideoH264ProfileIdc - pictureLayout*: VkVideoDecodeH264PictureLayoutFlagBitsKHR - VkVideoDecodeH264CapabilitiesKHR* = object - sType*: VkStructureType - pNext*: pointer - maxLevelIdc*: StdVideoH264LevelIdc - fieldOffsetGranularity*: VkOffset2D - VkVideoDecodeH264SessionParametersAddInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - stdSPSCount*: uint32 - pStdSPSs*: ptr StdVideoH264SequenceParameterSet - stdPPSCount*: uint32 - pStdPPSs*: ptr StdVideoH264PictureParameterSet - VkVideoDecodeH264SessionParametersCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - maxStdSPSCount*: uint32 - maxStdPPSCount*: uint32 - pParametersAddInfo*: ptr VkVideoDecodeH264SessionParametersAddInfoKHR - VkVideoDecodeH264PictureInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pStdPictureInfo*: ptr StdVideoDecodeH264PictureInfo - sliceCount*: uint32 - pSliceOffsets*: ptr uint32 - VkVideoDecodeH264DpbSlotInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pStdReferenceInfo*: ptr StdVideoDecodeH264ReferenceInfo - VkVideoDecodeH265ProfileInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - stdProfileIdc*: StdVideoH265ProfileIdc - VkVideoDecodeH265CapabilitiesKHR* = object - sType*: VkStructureType - pNext*: pointer - maxLevelIdc*: StdVideoH265LevelIdc - VkVideoDecodeH265SessionParametersAddInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - stdVPSCount*: uint32 - pStdVPSs*: ptr StdVideoH265VideoParameterSet - stdSPSCount*: uint32 - pStdSPSs*: ptr StdVideoH265SequenceParameterSet - stdPPSCount*: uint32 - pStdPPSs*: ptr StdVideoH265PictureParameterSet - VkVideoDecodeH265SessionParametersCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - maxStdVPSCount*: uint32 - maxStdSPSCount*: uint32 - maxStdPPSCount*: uint32 - pParametersAddInfo*: ptr VkVideoDecodeH265SessionParametersAddInfoKHR - VkVideoDecodeH265PictureInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pStdPictureInfo*: ptr StdVideoDecodeH265PictureInfo - sliceSegmentCount*: uint32 - pSliceSegmentOffsets*: ptr uint32 - VkVideoDecodeH265DpbSlotInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pStdReferenceInfo*: ptr StdVideoDecodeH265ReferenceInfo - VkVideoSessionCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - queueFamilyIndex*: uint32 - flags*: VkVideoSessionCreateFlagsKHR - pVideoProfile*: ptr VkVideoProfileInfoKHR - pictureFormat*: VkFormat - maxCodedExtent*: VkExtent2D - referencePictureFormat*: VkFormat - maxDpbSlots*: uint32 - maxActiveReferencePictures*: uint32 - pStdHeaderVersion*: ptr VkExtensionProperties - VkVideoSessionParametersCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoSessionParametersCreateFlagsKHR - videoSessionParametersTemplate*: VkVideoSessionParametersKHR - videoSession*: VkVideoSessionKHR - VkVideoSessionParametersUpdateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - updateSequenceCount*: uint32 - VkVideoBeginCodingInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoBeginCodingFlagsKHR - videoSession*: VkVideoSessionKHR - videoSessionParameters*: VkVideoSessionParametersKHR - referenceSlotCount*: uint32 - pReferenceSlots*: ptr VkVideoReferenceSlotInfoKHR - VkVideoEndCodingInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoEndCodingFlagsKHR - VkVideoCodingControlInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoCodingControlFlagsKHR - VkVideoEncodeUsageInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - videoUsageHints*: VkVideoEncodeUsageFlagsKHR - videoContentHints*: VkVideoEncodeContentFlagsKHR - tuningMode*: VkVideoEncodeTuningModeKHR - VkVideoEncodeInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoEncodeFlagsKHR - qualityLevel*: uint32 - dstBitstreamBuffer*: VkBuffer - dstBitstreamBufferOffset*: VkDeviceSize - dstBitstreamBufferMaxRange*: VkDeviceSize - srcPictureResource*: VkVideoPictureResourceInfoKHR - pSetupReferenceSlot*: ptr VkVideoReferenceSlotInfoKHR - referenceSlotCount*: uint32 - pReferenceSlots*: ptr VkVideoReferenceSlotInfoKHR - precedingExternallyEncodedBytes*: uint32 - VkVideoEncodeRateControlInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoEncodeRateControlFlagsKHR - rateControlMode*: VkVideoEncodeRateControlModeFlagBitsKHR - layerCount*: uint8 - pLayerConfigs*: ptr VkVideoEncodeRateControlLayerInfoKHR - VkVideoEncodeRateControlLayerInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - averageBitrate*: uint32 - maxBitrate*: uint32 - frameRateNumerator*: uint32 - frameRateDenominator*: uint32 - virtualBufferSizeInMs*: uint32 - initialVirtualBufferSizeInMs*: uint32 - VkVideoEncodeCapabilitiesKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoEncodeCapabilityFlagsKHR - rateControlModes*: VkVideoEncodeRateControlModeFlagsKHR - rateControlLayerCount*: uint8 - qualityLevelCount*: uint8 - inputImageDataFillAlignment*: VkExtent2D - VkVideoEncodeH264CapabilitiesEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoEncodeH264CapabilityFlagsEXT - inputModeFlags*: VkVideoEncodeH264InputModeFlagsEXT - outputModeFlags*: VkVideoEncodeH264OutputModeFlagsEXT - maxPPictureL0ReferenceCount*: uint8 - maxBPictureL0ReferenceCount*: uint8 - maxL1ReferenceCount*: uint8 - motionVectorsOverPicBoundariesFlag*: VkBool32 - maxBytesPerPicDenom*: uint32 - maxBitsPerMbDenom*: uint32 - log2MaxMvLengthHorizontal*: uint32 - log2MaxMvLengthVertical*: uint32 - VkVideoEncodeH264SessionParametersAddInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - stdSPSCount*: uint32 - pStdSPSs*: ptr StdVideoH264SequenceParameterSet - stdPPSCount*: uint32 - pStdPPSs*: ptr StdVideoH264PictureParameterSet - VkVideoEncodeH264SessionParametersCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - maxStdSPSCount*: uint32 - maxStdPPSCount*: uint32 - pParametersAddInfo*: ptr VkVideoEncodeH264SessionParametersAddInfoEXT - VkVideoEncodeH264DpbSlotInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - slotIndex*: int8 - pStdReferenceInfo*: ptr StdVideoEncodeH264ReferenceInfo - VkVideoEncodeH264VclFrameInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - pReferenceFinalLists*: ptr VkVideoEncodeH264ReferenceListsInfoEXT - naluSliceEntryCount*: uint32 - pNaluSliceEntries*: ptr VkVideoEncodeH264NaluSliceInfoEXT - pCurrentPictureInfo*: ptr StdVideoEncodeH264PictureInfo - VkVideoEncodeH264ReferenceListsInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - referenceList0EntryCount*: uint8 - pReferenceList0Entries*: ptr VkVideoEncodeH264DpbSlotInfoEXT - referenceList1EntryCount*: uint8 - pReferenceList1Entries*: ptr VkVideoEncodeH264DpbSlotInfoEXT - pMemMgmtCtrlOperations*: ptr StdVideoEncodeH264RefMemMgmtCtrlOperations - VkVideoEncodeH264EmitPictureParametersInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - spsId*: uint8 - emitSpsEnable*: VkBool32 - ppsIdEntryCount*: uint32 - ppsIdEntries*: ptr uint8 - VkVideoEncodeH264ProfileInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - stdProfileIdc*: StdVideoH264ProfileIdc - VkVideoEncodeH264NaluSliceInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - mbCount*: uint32 - pReferenceFinalLists*: ptr VkVideoEncodeH264ReferenceListsInfoEXT - pSliceHeaderStd*: ptr StdVideoEncodeH264SliceHeader - VkVideoEncodeH264RateControlInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - gopFrameCount*: uint32 - idrPeriod*: uint32 - consecutiveBFrameCount*: uint32 - rateControlStructure*: VkVideoEncodeH264RateControlStructureEXT - temporalLayerCount*: uint8 - VkVideoEncodeH264QpEXT* = object - qpI*: int32 - qpP*: int32 - qpB*: int32 - VkVideoEncodeH264FrameSizeEXT* = object - frameISize*: uint32 - framePSize*: uint32 - frameBSize*: uint32 - VkVideoEncodeH264RateControlLayerInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - temporalLayerId*: uint8 - useInitialRcQp*: VkBool32 - initialRcQp*: VkVideoEncodeH264QpEXT - useMinQp*: VkBool32 - minQp*: VkVideoEncodeH264QpEXT - useMaxQp*: VkBool32 - maxQp*: VkVideoEncodeH264QpEXT - useMaxFrameSize*: VkBool32 - maxFrameSize*: VkVideoEncodeH264FrameSizeEXT - VkVideoEncodeH265CapabilitiesEXT* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkVideoEncodeH265CapabilityFlagsEXT - inputModeFlags*: VkVideoEncodeH265InputModeFlagsEXT - outputModeFlags*: VkVideoEncodeH265OutputModeFlagsEXT - ctbSizes*: VkVideoEncodeH265CtbSizeFlagsEXT - transformBlockSizes*: VkVideoEncodeH265TransformBlockSizeFlagsEXT - maxPPictureL0ReferenceCount*: uint8 - maxBPictureL0ReferenceCount*: uint8 - maxL1ReferenceCount*: uint8 - maxSubLayersCount*: uint8 - minLog2MinLumaCodingBlockSizeMinus3*: uint8 - maxLog2MinLumaCodingBlockSizeMinus3*: uint8 - minLog2MinLumaTransformBlockSizeMinus2*: uint8 - maxLog2MinLumaTransformBlockSizeMinus2*: uint8 - minMaxTransformHierarchyDepthInter*: uint8 - maxMaxTransformHierarchyDepthInter*: uint8 - minMaxTransformHierarchyDepthIntra*: uint8 - maxMaxTransformHierarchyDepthIntra*: uint8 - maxDiffCuQpDeltaDepth*: uint8 - minMaxNumMergeCand*: uint8 - maxMaxNumMergeCand*: uint8 - VkVideoEncodeH265SessionParametersAddInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - stdVPSCount*: uint32 - pStdVPSs*: ptr StdVideoH265VideoParameterSet - stdSPSCount*: uint32 - pStdSPSs*: ptr StdVideoH265SequenceParameterSet - stdPPSCount*: uint32 - pStdPPSs*: ptr StdVideoH265PictureParameterSet - VkVideoEncodeH265SessionParametersCreateInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - maxStdVPSCount*: uint32 - maxStdSPSCount*: uint32 - maxStdPPSCount*: uint32 - pParametersAddInfo*: ptr VkVideoEncodeH265SessionParametersAddInfoEXT - VkVideoEncodeH265VclFrameInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - pReferenceFinalLists*: ptr VkVideoEncodeH265ReferenceListsInfoEXT - naluSliceSegmentEntryCount*: uint32 - pNaluSliceSegmentEntries*: ptr VkVideoEncodeH265NaluSliceSegmentInfoEXT - pCurrentPictureInfo*: ptr StdVideoEncodeH265PictureInfo - VkVideoEncodeH265EmitPictureParametersInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - vpsId*: uint8 - spsId*: uint8 - emitVpsEnable*: VkBool32 - emitSpsEnable*: VkBool32 - ppsIdEntryCount*: uint32 - ppsIdEntries*: ptr uint8 - VkVideoEncodeH265NaluSliceSegmentInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - ctbCount*: uint32 - pReferenceFinalLists*: ptr VkVideoEncodeH265ReferenceListsInfoEXT - pSliceSegmentHeaderStd*: ptr StdVideoEncodeH265SliceSegmentHeader - VkVideoEncodeH265RateControlInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - gopFrameCount*: uint32 - idrPeriod*: uint32 - consecutiveBFrameCount*: uint32 - rateControlStructure*: VkVideoEncodeH265RateControlStructureEXT - subLayerCount*: uint8 - VkVideoEncodeH265QpEXT* = object - qpI*: int32 - qpP*: int32 - qpB*: int32 - VkVideoEncodeH265FrameSizeEXT* = object - frameISize*: uint32 - framePSize*: uint32 - frameBSize*: uint32 - VkVideoEncodeH265RateControlLayerInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - temporalId*: uint8 - useInitialRcQp*: VkBool32 - initialRcQp*: VkVideoEncodeH265QpEXT - useMinQp*: VkBool32 - minQp*: VkVideoEncodeH265QpEXT - useMaxQp*: VkBool32 - maxQp*: VkVideoEncodeH265QpEXT - useMaxFrameSize*: VkBool32 - maxFrameSize*: VkVideoEncodeH265FrameSizeEXT - VkVideoEncodeH265ProfileInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - stdProfileIdc*: StdVideoH265ProfileIdc - VkVideoEncodeH265DpbSlotInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - slotIndex*: int8 - pStdReferenceInfo*: ptr StdVideoEncodeH265ReferenceInfo - VkVideoEncodeH265ReferenceListsInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - referenceList0EntryCount*: uint8 - pReferenceList0Entries*: ptr VkVideoEncodeH265DpbSlotInfoEXT - referenceList1EntryCount*: uint8 - pReferenceList1Entries*: ptr VkVideoEncodeH265DpbSlotInfoEXT - pReferenceModifications*: ptr StdVideoEncodeH265ReferenceModifications - StdVideoH264ProfileIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264LevelIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264ChromaFormatIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264PocType *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264SpsFlags *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264ScalingLists *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264SequenceParameterSetVui *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264AspectRatioIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264HrdParameters *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264SpsVuiFlags *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264WeightedBipredIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264PpsFlags *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264SliceType *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264CabacInitIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264DisableDeblockingFilterIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264PictureType *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264ModificationOfPicNumsIdc *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264MemMgmtControlOp *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoDecodeH264PictureInfo *{.header: "vk_video/vulkan_video_codec_h264std_decode.h".} = object - StdVideoDecodeH264ReferenceInfo *{.header: "vk_video/vulkan_video_codec_h264std_decode.h".} = object - StdVideoDecodeH264PictureInfoFlags *{.header: "vk_video/vulkan_video_codec_h264std_decode.h".} = object - StdVideoDecodeH264ReferenceInfoFlags *{.header: "vk_video/vulkan_video_codec_h264std_decode.h".} = object - StdVideoH264SequenceParameterSet *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH264PictureParameterSet *{.header: "vk_video/vulkan_video_codec_h264std.h".} = object - StdVideoH265ProfileIdc *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265VideoParameterSet *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265SequenceParameterSet *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265PictureParameterSet *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265DecPicBufMgr *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265HrdParameters *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265VpsFlags *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265LevelIdc *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265SpsFlags *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265ScalingLists *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265SequenceParameterSetVui *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265PredictorPaletteEntries *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265PpsFlags *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265SubLayerHrdParameters *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265HrdFlags *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265SpsVuiFlags *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265SliceType *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoH265PictureType *{.header: "vk_video/vulkan_video_codec_h265std.h".} = object - StdVideoDecodeH265PictureInfo *{.header: "vk_video/vulkan_video_codec_h265std_decode.h".} = object - StdVideoDecodeH265ReferenceInfo *{.header: "vk_video/vulkan_video_codec_h265std_decode.h".} = object - StdVideoDecodeH265PictureInfoFlags *{.header: "vk_video/vulkan_video_codec_h265std_decode.h".} = object - StdVideoDecodeH265ReferenceInfoFlags *{.header: "vk_video/vulkan_video_codec_h265std_decode.h".} = object - StdVideoEncodeH264SliceHeader *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object - StdVideoEncodeH264PictureInfo *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object - StdVideoEncodeH264ReferenceInfo *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object - StdVideoEncodeH264SliceHeaderFlags *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object - StdVideoEncodeH264RefMemMgmtCtrlOperations *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object - StdVideoEncodeH264PictureInfoFlags *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object - StdVideoEncodeH264ReferenceInfoFlags *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object - StdVideoEncodeH264RefMgmtFlags *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object - StdVideoEncodeH264RefListModEntry *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object - StdVideoEncodeH264RefPicMarkingEntry *{.header: "vk_video/vulkan_video_codec_h264std_encode.h".} = object - StdVideoEncodeH265PictureInfoFlags *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object - StdVideoEncodeH265PictureInfo *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object - StdVideoEncodeH265SliceSegmentHeader *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object - StdVideoEncodeH265ReferenceInfo *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object - StdVideoEncodeH265ReferenceModifications *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object - StdVideoEncodeH265SliceSegmentHeaderFlags *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object - StdVideoEncodeH265ReferenceInfoFlags *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object - StdVideoEncodeH265ReferenceModificationFlags *{.header: "vk_video/vulkan_video_codec_h265std_encode.h".} = object -# extension VK_KHR_video_queue -var - vkGetPhysicalDeviceVideoCapabilitiesKHR*: proc(physicalDevice: VkPhysicalDevice, pVideoProfile: ptr VkVideoProfileInfoKHR, pCapabilities: ptr VkVideoCapabilitiesKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceVideoFormatPropertiesKHR*: proc(physicalDevice: VkPhysicalDevice, pVideoFormatInfo: ptr VkPhysicalDeviceVideoFormatInfoKHR, pVideoFormatPropertyCount: ptr uint32, pVideoFormatProperties: ptr VkVideoFormatPropertiesKHR): VkResult {.stdcall.} - vkCreateVideoSessionKHR*: proc(device: VkDevice, pCreateInfo: ptr VkVideoSessionCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pVideoSession: ptr VkVideoSessionKHR): VkResult {.stdcall.} - vkDestroyVideoSessionKHR*: proc(device: VkDevice, videoSession: VkVideoSessionKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkGetVideoSessionMemoryRequirementsKHR*: proc(device: VkDevice, videoSession: VkVideoSessionKHR, pMemoryRequirementsCount: ptr uint32, pMemoryRequirements: ptr VkVideoSessionMemoryRequirementsKHR): VkResult {.stdcall.} - vkBindVideoSessionMemoryKHR*: proc(device: VkDevice, videoSession: VkVideoSessionKHR, bindSessionMemoryInfoCount: uint32, pBindSessionMemoryInfos: ptr VkBindVideoSessionMemoryInfoKHR): VkResult {.stdcall.} - vkCreateVideoSessionParametersKHR*: proc(device: VkDevice, pCreateInfo: ptr VkVideoSessionParametersCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pVideoSessionParameters: ptr VkVideoSessionParametersKHR): VkResult {.stdcall.} - vkUpdateVideoSessionParametersKHR*: proc(device: VkDevice, videoSessionParameters: VkVideoSessionParametersKHR, pUpdateInfo: ptr VkVideoSessionParametersUpdateInfoKHR): VkResult {.stdcall.} - vkDestroyVideoSessionParametersKHR*: proc(device: VkDevice, videoSessionParameters: VkVideoSessionParametersKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.} - vkCmdBeginVideoCodingKHR*: proc(commandBuffer: VkCommandBuffer, pBeginInfo: ptr VkVideoBeginCodingInfoKHR): void {.stdcall.} - vkCmdEndVideoCodingKHR*: proc(commandBuffer: VkCommandBuffer, pEndCodingInfo: ptr VkVideoEndCodingInfoKHR): void {.stdcall.} - vkCmdControlVideoCodingKHR*: proc(commandBuffer: VkCommandBuffer, pCodingControlInfo: ptr VkVideoCodingControlInfoKHR): void {.stdcall.} -proc loadVK_KHR_video_queue*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_VERSION_1_3(instance) - vkGetPhysicalDeviceVideoCapabilitiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pVideoProfile: ptr VkVideoProfileInfoKHR, pCapabilities: ptr VkVideoCapabilitiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoCapabilitiesKHR")) - vkGetPhysicalDeviceVideoFormatPropertiesKHR = cast[proc(physicalDevice: VkPhysicalDevice, pVideoFormatInfo: ptr VkPhysicalDeviceVideoFormatInfoKHR, pVideoFormatPropertyCount: ptr uint32, pVideoFormatProperties: ptr VkVideoFormatPropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoFormatPropertiesKHR")) - vkCreateVideoSessionKHR = cast[proc(device: VkDevice, pCreateInfo: ptr VkVideoSessionCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pVideoSession: ptr VkVideoSessionKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateVideoSessionKHR")) - vkDestroyVideoSessionKHR = cast[proc(device: VkDevice, videoSession: VkVideoSessionKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyVideoSessionKHR")) - vkGetVideoSessionMemoryRequirementsKHR = cast[proc(device: VkDevice, videoSession: VkVideoSessionKHR, pMemoryRequirementsCount: ptr uint32, pMemoryRequirements: ptr VkVideoSessionMemoryRequirementsKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetVideoSessionMemoryRequirementsKHR")) - vkBindVideoSessionMemoryKHR = cast[proc(device: VkDevice, videoSession: VkVideoSessionKHR, bindSessionMemoryInfoCount: uint32, pBindSessionMemoryInfos: ptr VkBindVideoSessionMemoryInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkBindVideoSessionMemoryKHR")) - vkCreateVideoSessionParametersKHR = cast[proc(device: VkDevice, pCreateInfo: ptr VkVideoSessionParametersCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pVideoSessionParameters: ptr VkVideoSessionParametersKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateVideoSessionParametersKHR")) - vkUpdateVideoSessionParametersKHR = cast[proc(device: VkDevice, videoSessionParameters: VkVideoSessionParametersKHR, pUpdateInfo: ptr VkVideoSessionParametersUpdateInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkUpdateVideoSessionParametersKHR")) - vkDestroyVideoSessionParametersKHR = cast[proc(device: VkDevice, videoSessionParameters: VkVideoSessionParametersKHR, pAllocator: ptr VkAllocationCallbacks): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkDestroyVideoSessionParametersKHR")) - vkCmdBeginVideoCodingKHR = cast[proc(commandBuffer: VkCommandBuffer, pBeginInfo: ptr VkVideoBeginCodingInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdBeginVideoCodingKHR")) - vkCmdEndVideoCodingKHR = cast[proc(commandBuffer: VkCommandBuffer, pEndCodingInfo: ptr VkVideoEndCodingInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEndVideoCodingKHR")) - vkCmdControlVideoCodingKHR = cast[proc(commandBuffer: VkCommandBuffer, pCodingControlInfo: ptr VkVideoCodingControlInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdControlVideoCodingKHR")) - -# extension VK_KHR_video_encode_queue -var - vkCmdEncodeVideoKHR*: proc(commandBuffer: VkCommandBuffer, pEncodeInfo: ptr VkVideoEncodeInfoKHR): void {.stdcall.} -proc loadVK_KHR_video_encode_queue*(instance: VkInstance) = - loadVK_KHR_video_queue(instance) - loadVK_VERSION_1_3(instance) - vkCmdEncodeVideoKHR = cast[proc(commandBuffer: VkCommandBuffer, pEncodeInfo: ptr VkVideoEncodeInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdEncodeVideoKHR")) - -# extension VK_KHR_video_decode_queue -var - vkCmdDecodeVideoKHR*: proc(commandBuffer: VkCommandBuffer, pDecodeInfo: ptr VkVideoDecodeInfoKHR): void {.stdcall.} -proc loadVK_KHR_video_decode_queue*(instance: VkInstance) = - loadVK_KHR_video_queue(instance) - loadVK_VERSION_1_3(instance) - vkCmdDecodeVideoKHR = cast[proc(commandBuffer: VkCommandBuffer, pDecodeInfo: ptr VkVideoDecodeInfoKHR): void {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCmdDecodeVideoKHR")) - -proc loadVK_KHR_portability_subset*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - -proc loadVK_EXT_video_encode_h264*(instance: VkInstance) = - loadVK_KHR_video_encode_queue(instance) - -proc loadVK_EXT_video_encode_h265*(instance: VkInstance) = - loadVK_KHR_video_encode_queue(instance) - -proc loadVK_KHR_video_decode_h265*(instance: VkInstance) = - loadVK_KHR_video_decode_queue(instance) - -proc loadVK_KHR_video_decode_h264*(instance: VkInstance) = - loadVK_KHR_video_decode_queue(instance) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/sci.nim --- a/src/semicongine/vulkan/platform/sci.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -type - VkExportMemorySciBufInfoNV* = object - sType*: VkStructureType - pNext*: pointer - pAttributes*: NvSciBufAttrList - VkImportMemorySciBufInfoNV* = object - sType*: VkStructureType - pNext*: pointer - handleType*: VkExternalMemoryHandleTypeFlagBits - handle*: NvSciBufObj - VkMemoryGetSciBufInfoNV* = object - sType*: VkStructureType - pNext*: pointer - memory*: VkDeviceMemory - handleType*: VkExternalMemoryHandleTypeFlagBits - VkMemorySciBufPropertiesNV* = object - sType*: VkStructureType - pNext*: pointer - memoryTypeBits*: uint32 - VkPhysicalDeviceExternalMemorySciBufFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - sciBufImport*: VkBool32 - sciBufExport*: VkBool32 - VkPhysicalDeviceExternalSciBufFeaturesNV* = object - VkExportFenceSciSyncInfoNV* = object - sType*: VkStructureType - pNext*: pointer - pAttributes*: NvSciSyncAttrList - VkImportFenceSciSyncInfoNV* = object - sType*: VkStructureType - pNext*: pointer - fence*: VkFence - handleType*: VkExternalFenceHandleTypeFlagBits - handle*: pointer - VkFenceGetSciSyncInfoNV* = object - sType*: VkStructureType - pNext*: pointer - fence*: VkFence - handleType*: VkExternalFenceHandleTypeFlagBits - VkExportSemaphoreSciSyncInfoNV* = object - sType*: VkStructureType - pNext*: pointer - pAttributes*: NvSciSyncAttrList - VkImportSemaphoreSciSyncInfoNV* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - handleType*: VkExternalSemaphoreHandleTypeFlagBits - handle*: pointer - VkSemaphoreGetSciSyncInfoNV* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - handleType*: VkExternalSemaphoreHandleTypeFlagBits - VkSciSyncAttributesInfoNV* = object - sType*: VkStructureType - pNext*: pointer - clientType*: VkSciSyncClientTypeNV - primitiveType*: VkSciSyncPrimitiveTypeNV - VkPhysicalDeviceExternalSciSyncFeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - sciSyncFence*: VkBool32 - sciSyncSemaphore*: VkBool32 - sciSyncImport*: VkBool32 - sciSyncExport*: VkBool32 - VkPhysicalDeviceExternalSciSync2FeaturesNV* = object - sType*: VkStructureType - pNext*: pointer - sciSyncFence*: VkBool32 - sciSyncSemaphore2*: VkBool32 - sciSyncImport*: VkBool32 - sciSyncExport*: VkBool32 - VkSemaphoreSciSyncPoolCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - handle*: NvSciSyncObj - VkSemaphoreSciSyncCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - semaphorePool*: VkSemaphoreSciSyncPoolNV - pFence*: ptr NvSciSyncFence - VkDeviceSemaphoreSciSyncPoolReservationCreateInfoNV* = object - sType*: VkStructureType - pNext*: pointer - semaphoreSciSyncPoolRequestCount*: uint32 - NvSciSyncAttrList *{.header: "nvscisync.h".} = object - NvSciSyncObj *{.header: "nvscisync.h".} = object - NvSciSyncFence *{.header: "nvscisync.h".} = object - NvSciBufAttrList *{.header: "nvscibuf.h".} = object - NvSciBufObj *{.header: "nvscibuf.h".} = object \ No newline at end of file diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/screen.nim --- a/src/semicongine/vulkan/platform/screen.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -type - VkScreenSurfaceCreateInfoQNX* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkScreenSurfaceCreateFlagsQNX - context*: ptr screen_context - window*: ptr screen_window - screen_context *{.header: "screen/screen.h".} = object - screen_window *{.header: "screen/screen.h".} = object -# extension VK_QNX_screen_surface -var - vkCreateScreenSurfaceQNX*: proc(instance: VkInstance, pCreateInfo: ptr VkScreenSurfaceCreateInfoQNX, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceScreenPresentationSupportQNX*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, window: ptr screen_window): VkBool32 {.stdcall.} -proc loadVK_QNX_screen_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateScreenSurfaceQNX = cast[proc(instance: VkInstance, pCreateInfo: ptr VkScreenSurfaceCreateInfoQNX, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateScreenSurfaceQNX")) - vkGetPhysicalDeviceScreenPresentationSupportQNX = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, window: ptr screen_window): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceScreenPresentationSupportQNX")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/vi.nim --- a/src/semicongine/vulkan/platform/vi.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -type - VkViSurfaceCreateInfoNN* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkViSurfaceCreateFlagsNN - window*: pointer -# extension VK_NN_vi_surface -var - vkCreateViSurfaceNN*: proc(instance: VkInstance, pCreateInfo: ptr VkViSurfaceCreateInfoNN, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} -proc loadVK_NN_vi_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateViSurfaceNN = cast[proc(instance: VkInstance, pCreateInfo: ptr VkViSurfaceCreateInfoNN, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateViSurfaceNN")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/wayland.nim --- a/src/semicongine/vulkan/platform/wayland.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -type - VkWaylandSurfaceCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkWaylandSurfaceCreateFlagsKHR - display*: ptr wl_display - surface*: ptr wl_surface - wl_display *{.header: "wayland-client.h".} = object - wl_surface *{.header: "wayland-client.h".} = object -# extension VK_KHR_wayland_surface -var - vkCreateWaylandSurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkWaylandSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceWaylandPresentationSupportKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, display: ptr wl_display): VkBool32 {.stdcall.} -proc loadVK_KHR_wayland_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateWaylandSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkWaylandSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR")) - vkGetPhysicalDeviceWaylandPresentationSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, display: ptr wl_display): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/win32.nim --- a/src/semicongine/vulkan/platform/win32.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -type - VkWin32SurfaceCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkWin32SurfaceCreateFlagsKHR - hinstance*: HINSTANCE - hwnd*: HWND - VkImportMemoryWin32HandleInfoNV* = object - sType*: VkStructureType - pNext*: pointer - handleType*: VkExternalMemoryHandleTypeFlagsNV - handle*: HANDLE - VkExportMemoryWin32HandleInfoNV* = object - sType*: VkStructureType - pNext*: pointer - pAttributes*: ptr SECURITY_ATTRIBUTES - dwAccess*: DWORD - VkWin32KeyedMutexAcquireReleaseInfoNV* = object - sType*: VkStructureType - pNext*: pointer - acquireCount*: uint32 - pAcquireSyncs*: ptr VkDeviceMemory - pAcquireKeys*: ptr uint64 - pAcquireTimeoutMilliseconds*: ptr uint32 - releaseCount*: uint32 - pReleaseSyncs*: ptr VkDeviceMemory - pReleaseKeys*: ptr uint64 - VkImportMemoryWin32HandleInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - handleType*: VkExternalMemoryHandleTypeFlagBits - handle*: HANDLE - name*: LPCWSTR - VkExportMemoryWin32HandleInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pAttributes*: ptr SECURITY_ATTRIBUTES - dwAccess*: DWORD - name*: LPCWSTR - VkMemoryWin32HandlePropertiesKHR* = object - sType*: VkStructureType - pNext*: pointer - memoryTypeBits*: uint32 - VkMemoryGetWin32HandleInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - memory*: VkDeviceMemory - handleType*: VkExternalMemoryHandleTypeFlagBits - VkWin32KeyedMutexAcquireReleaseInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - acquireCount*: uint32 - pAcquireSyncs*: ptr VkDeviceMemory - pAcquireKeys*: ptr uint64 - pAcquireTimeouts*: ptr uint32 - releaseCount*: uint32 - pReleaseSyncs*: ptr VkDeviceMemory - pReleaseKeys*: ptr uint64 - VkImportSemaphoreWin32HandleInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - flags*: VkSemaphoreImportFlags - handleType*: VkExternalSemaphoreHandleTypeFlagBits - handle*: HANDLE - name*: LPCWSTR - VkExportSemaphoreWin32HandleInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pAttributes*: ptr SECURITY_ATTRIBUTES - dwAccess*: DWORD - name*: LPCWSTR - VkD3D12FenceSubmitInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - waitSemaphoreValuesCount*: uint32 - pWaitSemaphoreValues*: ptr uint64 - signalSemaphoreValuesCount*: uint32 - pSignalSemaphoreValues*: ptr uint64 - VkSemaphoreGetWin32HandleInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - semaphore*: VkSemaphore - handleType*: VkExternalSemaphoreHandleTypeFlagBits - VkImportFenceWin32HandleInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - fence*: VkFence - flags*: VkFenceImportFlags - handleType*: VkExternalFenceHandleTypeFlagBits - handle*: HANDLE - name*: LPCWSTR - VkExportFenceWin32HandleInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - pAttributes*: ptr SECURITY_ATTRIBUTES - dwAccess*: DWORD - name*: LPCWSTR - VkFenceGetWin32HandleInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - fence*: VkFence - handleType*: VkExternalFenceHandleTypeFlagBits - VkSurfaceFullScreenExclusiveInfoEXT* = object - sType*: VkStructureType - pNext*: pointer - fullScreenExclusive*: VkFullScreenExclusiveEXT - VkSurfaceFullScreenExclusiveWin32InfoEXT* = object - sType*: VkStructureType - pNext*: pointer - hmonitor*: HMONITOR - VkSurfaceCapabilitiesFullScreenExclusiveEXT* = object - sType*: VkStructureType - pNext*: pointer - fullScreenExclusiveSupported*: VkBool32 - HINSTANCE *{.header: "windows.h".} = object - HWND *{.header: "windows.h".} = object - HMONITOR *{.header: "windows.h".} = object - HANDLE *{.header: "windows.h".} = object - SECURITY_ATTRIBUTES *{.header: "windows.h".} = object - DWORD *{.header: "windows.h".} = object - LPCWSTR *{.header: "windows.h".} = object -# extension VK_KHR_external_semaphore_win32 -var - vkImportSemaphoreWin32HandleKHR*: proc(device: VkDevice, pImportSemaphoreWin32HandleInfo: ptr VkImportSemaphoreWin32HandleInfoKHR): VkResult {.stdcall.} - vkGetSemaphoreWin32HandleKHR*: proc(device: VkDevice, pGetWin32HandleInfo: ptr VkSemaphoreGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.} -proc loadVK_KHR_external_semaphore_win32*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkImportSemaphoreWin32HandleKHR = cast[proc(device: VkDevice, pImportSemaphoreWin32HandleInfo: ptr VkImportSemaphoreWin32HandleInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkImportSemaphoreWin32HandleKHR")) - vkGetSemaphoreWin32HandleKHR = cast[proc(device: VkDevice, pGetWin32HandleInfo: ptr VkSemaphoreGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetSemaphoreWin32HandleKHR")) - -# extension VK_KHR_external_memory_win32 -var - vkGetMemoryWin32HandleKHR*: proc(device: VkDevice, pGetWin32HandleInfo: ptr VkMemoryGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.} - vkGetMemoryWin32HandlePropertiesKHR*: proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, handle: HANDLE, pMemoryWin32HandleProperties: ptr VkMemoryWin32HandlePropertiesKHR): VkResult {.stdcall.} -proc loadVK_KHR_external_memory_win32*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkGetMemoryWin32HandleKHR = cast[proc(device: VkDevice, pGetWin32HandleInfo: ptr VkMemoryGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryWin32HandleKHR")) - vkGetMemoryWin32HandlePropertiesKHR = cast[proc(device: VkDevice, handleType: VkExternalMemoryHandleTypeFlagBits, handle: HANDLE, pMemoryWin32HandleProperties: ptr VkMemoryWin32HandlePropertiesKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryWin32HandlePropertiesKHR")) - -# extension VK_KHR_external_fence_win32 -var - vkImportFenceWin32HandleKHR*: proc(device: VkDevice, pImportFenceWin32HandleInfo: ptr VkImportFenceWin32HandleInfoKHR): VkResult {.stdcall.} - vkGetFenceWin32HandleKHR*: proc(device: VkDevice, pGetWin32HandleInfo: ptr VkFenceGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.} -proc loadVK_KHR_external_fence_win32*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - vkImportFenceWin32HandleKHR = cast[proc(device: VkDevice, pImportFenceWin32HandleInfo: ptr VkImportFenceWin32HandleInfoKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkImportFenceWin32HandleKHR")) - vkGetFenceWin32HandleKHR = cast[proc(device: VkDevice, pGetWin32HandleInfo: ptr VkFenceGetWin32HandleInfoKHR, pHandle: ptr HANDLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetFenceWin32HandleKHR")) - -proc loadVK_KHR_win32_keyed_mutex*(instance: VkInstance) = - loadVK_KHR_external_memory_win32(instance) - -# extension VK_NV_external_memory_win32 -var - vkGetMemoryWin32HandleNV*: proc(device: VkDevice, memory: VkDeviceMemory, handleType: VkExternalMemoryHandleTypeFlagsNV, pHandle: ptr HANDLE): VkResult {.stdcall.} -proc loadVK_NV_external_memory_win32*(instance: VkInstance) = - loadVK_NV_external_memory(instance) - vkGetMemoryWin32HandleNV = cast[proc(device: VkDevice, memory: VkDeviceMemory, handleType: VkExternalMemoryHandleTypeFlagsNV, pHandle: ptr HANDLE): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetMemoryWin32HandleNV")) - -# extension VK_EXT_full_screen_exclusive -var - vkGetPhysicalDeviceSurfacePresentModes2EXT*: proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pPresentModeCount: ptr uint32, pPresentModes: ptr VkPresentModeKHR): VkResult {.stdcall.} - vkAcquireFullScreenExclusiveModeEXT*: proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.} - vkReleaseFullScreenExclusiveModeEXT*: proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.} - vkGetDeviceGroupSurfacePresentModes2EXT*: proc(device: VkDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pModes: ptr VkDeviceGroupPresentModeFlagsKHR): VkResult {.stdcall.} -proc loadVK_EXT_full_screen_exclusive*(instance: VkInstance) = - loadVK_VERSION_1_1(instance) - loadVK_KHR_surface(instance) - loadVK_KHR_get_surface_capabilities2(instance) - loadVK_KHR_swapchain(instance) - vkGetPhysicalDeviceSurfacePresentModes2EXT = cast[proc(physicalDevice: VkPhysicalDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pPresentModeCount: ptr uint32, pPresentModes: ptr VkPresentModeKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModes2EXT")) - vkAcquireFullScreenExclusiveModeEXT = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireFullScreenExclusiveModeEXT")) - vkReleaseFullScreenExclusiveModeEXT = cast[proc(device: VkDevice, swapchain: VkSwapchainKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkReleaseFullScreenExclusiveModeEXT")) - vkGetDeviceGroupSurfacePresentModes2EXT = cast[proc(device: VkDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pModes: ptr VkDeviceGroupPresentModeFlagsKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceGroupSurfacePresentModes2EXT")) - vkGetDeviceGroupSurfacePresentModes2EXT = cast[proc(device: VkDevice, pSurfaceInfo: ptr VkPhysicalDeviceSurfaceInfo2KHR, pModes: ptr VkDeviceGroupPresentModeFlagsKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetDeviceGroupSurfacePresentModes2EXT")) - -# extension VK_KHR_win32_surface -var - vkCreateWin32SurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkWin32SurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceWin32PresentationSupportKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32): VkBool32 {.stdcall.} -proc loadVK_KHR_win32_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateWin32SurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkWin32SurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR")) - vkGetPhysicalDeviceWin32PresentationSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR")) - -# extension VK_NV_acquire_winrt_display -var - vkAcquireWinrtDisplayNV*: proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR): VkResult {.stdcall.} - vkGetWinrtDisplayNV*: proc(physicalDevice: VkPhysicalDevice, deviceRelativeId: uint32, pDisplay: ptr VkDisplayKHR): VkResult {.stdcall.} -proc loadVK_NV_acquire_winrt_display*(instance: VkInstance) = - loadVK_EXT_direct_mode_display(instance) - vkAcquireWinrtDisplayNV = cast[proc(physicalDevice: VkPhysicalDevice, display: VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireWinrtDisplayNV")) - vkGetWinrtDisplayNV = cast[proc(physicalDevice: VkPhysicalDevice, deviceRelativeId: uint32, pDisplay: ptr VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetWinrtDisplayNV")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/xcb.nim --- a/src/semicongine/vulkan/platform/xcb.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -type - VkXcbSurfaceCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkXcbSurfaceCreateFlagsKHR - connection*: ptr xcb_connection_t - window*: xcb_window_t - xcb_connection_t *{.header: "xcb/xcb.h".} = object - xcb_visualid_t *{.header: "xcb/xcb.h".} = object - xcb_window_t *{.header: "xcb/xcb.h".} = object -# extension VK_KHR_xcb_surface -var - vkCreateXcbSurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkXcbSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceXcbPresentationSupportKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, connection: ptr xcb_connection_t, visual_id: xcb_visualid_t): VkBool32 {.stdcall.} -proc loadVK_KHR_xcb_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateXcbSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkXcbSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR")) - vkGetPhysicalDeviceXcbPresentationSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, connection: ptr xcb_connection_t, visual_id: xcb_visualid_t): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/xlib.nim --- a/src/semicongine/vulkan/platform/xlib.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -type - VkXlibSurfaceCreateInfoKHR* = object - sType*: VkStructureType - pNext*: pointer - flags*: VkXlibSurfaceCreateFlagsKHR - dpy*: ptr Display - window*: Window - Display *{.header: "X11/Xlib.h".} = object - VisualID *{.header: "X11/Xlib.h".} = object - Window *{.header: "X11/Xlib.h".} = object -# extension VK_KHR_xlib_surface -var - vkCreateXlibSurfaceKHR*: proc(instance: VkInstance, pCreateInfo: ptr VkXlibSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.} - vkGetPhysicalDeviceXlibPresentationSupportKHR*: proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, dpy: ptr Display, visualID: VisualID): VkBool32 {.stdcall.} -proc loadVK_KHR_xlib_surface*(instance: VkInstance) = - loadVK_KHR_surface(instance) - vkCreateXlibSurfaceKHR = cast[proc(instance: VkInstance, pCreateInfo: ptr VkXlibSurfaceCreateInfoKHR, pAllocator: ptr VkAllocationCallbacks, pSurface: ptr VkSurfaceKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR")) - vkGetPhysicalDeviceXlibPresentationSupportKHR = cast[proc(physicalDevice: VkPhysicalDevice, queueFamilyIndex: uint32, dpy: ptr Display, visualID: VisualID): VkBool32 {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/platform/xlib_xrandr.nim --- a/src/semicongine/vulkan/platform/xlib_xrandr.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -type - Display *{.header: "X11/Xlib.h".} = object - VisualID *{.header: "X11/Xlib.h".} = object - Window *{.header: "X11/Xlib.h".} = object - RROutput *{.header: "X11/extensions/Xrandr.h".} = object -# extension VK_EXT_acquire_xlib_display -var - vkAcquireXlibDisplayEXT*: proc(physicalDevice: VkPhysicalDevice, dpy: ptr Display, display: VkDisplayKHR): VkResult {.stdcall.} - vkGetRandROutputDisplayEXT*: proc(physicalDevice: VkPhysicalDevice, dpy: ptr Display, rrOutput: RROutput, pDisplay: ptr VkDisplayKHR): VkResult {.stdcall.} -proc loadVK_EXT_acquire_xlib_display*(instance: VkInstance) = - loadVK_EXT_direct_mode_display(instance) - vkAcquireXlibDisplayEXT = cast[proc(physicalDevice: VkPhysicalDevice, dpy: ptr Display, display: VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkAcquireXlibDisplayEXT")) - vkGetRandROutputDisplayEXT = cast[proc(physicalDevice: VkPhysicalDevice, dpy: ptr Display, rrOutput: RROutput, pDisplay: ptr VkDisplayKHR): VkResult {.stdcall.}](vkGetInstanceProcAddr(instance, "vkGetRandROutputDisplayEXT")) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/renderpass.nim --- a/src/semicongine/vulkan/renderpass.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -import std/options - -import ../core -import ../material -import ./device -import ./physicaldevice -import ./pipeline -import ./shader -import ./framebuffer - -type - Subpass* = object - clearColor*: Vec4f - pipelineBindPoint*: VkPipelineBindPoint - flags: VkSubpassDescriptionFlags - outputs: seq[VkAttachmentReference] - depthStencil: Option[VkAttachmentReference] - shaderPipelines*: seq[(MaterialType, ShaderPipeline)] - RenderPass* = object - vk*: VkRenderPass - device*: Device - subpasses*: seq[Subpass] - -proc createRenderPass*( - device: Device, - attachments: seq[VkAttachmentDescription], - subpasses: seq[Subpass], - dependencies: seq[VkSubpassDependency], -): RenderPass = - assert device.vk.valid - var pAttachments = attachments - var pSubpasses = subpasses - var pDependencies = dependencies - - var subpassesList: seq[VkSubpassDescription] - for subpass in pSubpasses.mitems: - subpassesList.add VkSubpassDescription( - flags: subpass.flags, - pipelineBindPoint: subpass.pipelineBindPoint, - inputAttachmentCount: 0, - pInputAttachments: nil, - colorAttachmentCount: uint32(subpass.outputs.len), - pColorAttachments: subpass.outputs.toCPointer, - pResolveAttachments: nil, - pDepthStencilAttachment: if subpass.depthStencil.isSome: addr(subpass.depthStencil.get) else: nil, - preserveAttachmentCount: 0, - pPreserveAttachments: nil, - ) - - var createInfo = VkRenderPassCreateInfo( - sType: VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - attachmentCount: uint32(pAttachments.len), - pAttachments: pAttachments.toCPointer, - subpassCount: uint32(subpassesList.len), - pSubpasses: subpassesList.toCPointer, - dependencyCount: uint32(pDependencies.len), - pDependencies: pDependencies.toCPointer, - ) - result.device = device - result.subpasses = pSubpasses - checkVkResult device.vk.vkCreateRenderPass(addr(createInfo), nil, addr(result.vk)) - -proc simpleForwardRenderPass*( - device: Device, - shaders: openArray[(MaterialType, ShaderConfiguration)], - inFlightFrames=2, - clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32]), - backFaceCulling=true, -): RenderPass = - # TODO: check wether materials are compatible with the assigned shaders - {.warning: "Need to implement material -> shader compatability" .} - - assert device.vk.valid - for (_, shaderconfig) in shaders: - assert shaderconfig.outputs.len == 1 - var - attachments = @[VkAttachmentDescription( - format: device.physicalDevice.getSurfaceFormats().filterSurfaceFormat().format, - samples: VK_SAMPLE_COUNT_1_BIT, - loadOp: VK_ATTACHMENT_LOAD_OP_CLEAR, - storeOp: VK_ATTACHMENT_STORE_OP_STORE, - stencilLoadOp: VK_ATTACHMENT_LOAD_OP_DONT_CARE, - stencilStoreOp: VK_ATTACHMENT_STORE_OP_DONT_CARE, - initialLayout: VK_IMAGE_LAYOUT_UNDEFINED, - finalLayout: VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - )] - subpasses = @[ - Subpass( - pipelineBindPoint: VK_PIPELINE_BIND_POINT_GRAPHICS, - outputs: @[VkAttachmentReference(attachment: 0, layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)], - clearColor: clearColor - ) - ] - # dependencies seems to be optional, TODO: benchmark difference - dependencies = @[VkSubpassDependency( - srcSubpass: VK_SUBPASS_EXTERNAL, - dstSubpass: 0, - srcStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT], - srcAccessMask: VkAccessFlags(0), - dstStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT], - dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT], - )] - result = device.createRenderPass(attachments=attachments, subpasses=subpasses, dependencies=dependencies) - for (materialtype, shaderconfig) in shaders: - result.subpasses[0].shaderPipelines.add (materialtype, device.createPipeline(result.vk, shaderconfig, inFlightFrames, 0, backFaceCulling=backFaceCulling)) - - -proc beginRenderCommands*(commandBuffer: VkCommandBuffer, renderpass: RenderPass, framebuffer: Framebuffer) = - assert commandBuffer.valid - assert renderpass.vk.valid - assert framebuffer.vk.valid - let - w = framebuffer.dimension.x - h = framebuffer.dimension.y - - var clearColors: seq[VkClearValue] - for subpass in renderpass.subpasses: - clearColors.add(VkClearValue(color: VkClearColorValue(float32: subpass.clearColor))) - var - beginInfo = VkCommandBufferBeginInfo( - sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - pInheritanceInfo: nil, - ) - renderPassInfo = VkRenderPassBeginInfo( - sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - renderPass: renderPass.vk, - framebuffer: framebuffer.vk, - renderArea: VkRect2D( - offset: VkOffset2D(x: 0, y: 0), - extent: VkExtent2D(width: w, height: h), - ), - clearValueCount: uint32(clearColors.len), - pClearValues: clearColors.toCPointer(), - ) - viewport = VkViewport( - x: 0.0, - y: 0.0, - width: (float)w, - height: (float)h, - minDepth: 0.0, - maxDepth: 1.0, - ) - scissor = VkRect2D( - offset: VkOffset2D(x: 0, y: 0), - extent: VkExtent2D(width: w, height: h) - ) - checkVkResult commandBuffer.vkResetCommandBuffer(VkCommandBufferResetFlags(0)) - checkVkResult commandBuffer.vkBeginCommandBuffer(addr(beginInfo)) - commandBuffer.vkCmdBeginRenderPass(addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE) - commandBuffer.vkCmdSetViewport(firstViewport=0, viewportCount=1, addr(viewport)) - commandBuffer.vkCmdSetScissor(firstScissor=0, scissorCount=1, addr(scissor)) - -proc endRenderCommands*(commandBuffer: VkCommandBuffer) = - commandBuffer.vkCmdEndRenderPass() - checkVkResult commandBuffer.vkEndCommandBuffer() - - -proc destroy*(renderPass: var RenderPass) = - assert renderPass.device.vk.valid - assert renderPass.vk.valid - renderPass.device.vk.vkDestroyRenderPass(renderPass.vk, nil) - renderPass.vk.reset - for i in 0 ..< renderPass.subpasses.len: - for _, pipeline in renderPass.subpasses[i].shaderPipelines.mitems: - pipeline.destroy() - renderPass.subpasses = @[] diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/shader.nim --- a/src/semicongine/vulkan/shader.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,218 +0,0 @@ -import std/typetraits -import std/os -import std/enumerate -import std/logging -import std/hashes -import std/strformat -import std/strutils -import std/compilesettings - -import ../core -import ./device - -const DEFAULT_SHADER_VERSION = 450 -const DEFAULT_SHADER_ENTRYPOINT = "main" - -let logger = newConsoleLogger() -addHandler(logger) - -type - ShaderModule* = object - device: Device - vk*: VkShaderModule - stage*: VkShaderStageFlagBits - configuration*: ShaderConfiguration - ShaderConfiguration* = object - vertexBinary: seq[uint32] - fragmentBinary: seq[uint32] - entrypoint: string - inputs*: seq[ShaderAttribute] - intermediates*: seq[ShaderAttribute] - outputs*: seq[ShaderAttribute] - uniforms*: seq[ShaderAttribute] - samplers*: seq[ShaderAttribute] - - -proc compileGlslToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string, entrypoint: string): seq[uint32] {.compileTime.} = - func stage2string(stage: VkShaderStageFlagBits): string {.compileTime.} = - case stage - of VK_SHADER_STAGE_VERTEX_BIT: "vert" - of VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: "tesc" - of VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: "tese" - of VK_SHADER_STAGE_GEOMETRY_BIT: "geom" - of VK_SHADER_STAGE_FRAGMENT_BIT: "frag" - of VK_SHADER_STAGE_COMPUTE_BIT: "comp" - else: "" - - when defined(nimcheck): # will not run if nimcheck is running - return result - - let - stagename = stage2string(stage) - shaderHash = hash(shaderSource) - # cross compilation for windows workaround, sorry computer - shaderfile = getTempDir() / &"shader_{shaderHash}.{stagename}" - projectPath = querySetting(projectPath) - - echo "shader of type ", stage, ", entrypoint ", entrypoint - for i, line in enumerate(shaderSource.splitlines()): - echo " ", i + 1, " ", line - var glslExe = "glslangValidator" - when defined(windows): - glslExe = glslExe & "." & ExeExt - let command = &"{projectPath.joinPath(glslExe)} --entry-point {entrypoint} -V --stdin -S {stagename} -o {shaderfile}" - echo "run: ", command - discard staticExecChecked( - command = command, - input = shaderSource - ) - - when defined(mingw) and defined(linux): # required for crosscompilation, path separators get messed up - let shaderbinary = staticRead shaderfile.replace("\\", "/") - else: - let shaderbinary = staticRead shaderfile - - var i = 0 - while i < shaderbinary.len: - result.add( - (uint32(shaderbinary[i + 0]) shl 0) or - (uint32(shaderbinary[i + 1]) shl 8) or - (uint32(shaderbinary[i + 2]) shl 16) or - (uint32(shaderbinary[i + 3]) shl 24) - ) - i += 4 - -proc compileGlslCode*( - stage: VkShaderStageFlagBits, - inputs: openArray[ShaderAttribute]=[], - uniforms: openArray[ShaderAttribute]=[], - samplers: openArray[ShaderAttribute]=[], - outputs: openArray[ShaderAttribute]=[], - version=DEFAULT_SHADER_VERSION , - entrypoint=DEFAULT_SHADER_ENTRYPOINT , - main: string -): seq[uint32] {.compileTime.} = - - let code = @[&"#version {version}", "#extension GL_EXT_scalar_block_layout : require", ""] & - (if inputs.len > 0: inputs.glslInput() & @[""] else: @[]) & - (if uniforms.len > 0: uniforms.glslUniforms(binding=0) & @[""] else: @[]) & - (if samplers.len > 0: samplers.glslSamplers(basebinding=if uniforms.len > 0: 1 else: 0) & @[""] else: @[]) & - (if outputs.len > 0: outputs.glslOutput() & @[""] else: @[]) & - @[&"void {entrypoint}(){{"] & - main & - @[&"}}"] - compileGlslToSPIRV(stage, code.join("\n"), entrypoint) - -proc createShaderConfiguration*( - inputs: openArray[ShaderAttribute]=[], - intermediates: openArray[ShaderAttribute]=[], - outputs: openArray[ShaderAttribute]=[], - uniforms: openArray[ShaderAttribute]=[], - samplers: openArray[ShaderAttribute]=[], - version=DEFAULT_SHADER_VERSION , - entrypoint=DEFAULT_SHADER_ENTRYPOINT , - vertexCode: string, - fragmentCode: string, -): ShaderConfiguration {.compileTime.} = - ShaderConfiguration( - vertexBinary: compileGlslCode( - stage=VK_SHADER_STAGE_VERTEX_BIT, - inputs=inputs, - outputs=intermediates, - uniforms=uniforms, - samplers=samplers, - main=vertexCode, - ), - fragmentBinary: compileGlslCode( - stage=VK_SHADER_STAGE_FRAGMENT_BIT, - inputs=intermediates, - outputs=outputs, - uniforms=uniforms, - samplers=samplers, - main=fragmentCode, - ), - entrypoint: entrypoint, - inputs: @inputs, - intermediates: @intermediates, - outputs: @outputs, - uniforms: @uniforms, - samplers: @samplers, - ) - - -proc createShaderModules*( - device: Device, - shaderConfiguration: ShaderConfiguration, -): (ShaderModule, ShaderModule) = - assert device.vk.valid - assert len(shaderConfiguration.vertexBinary) > 0 - assert len(shaderConfiguration.fragmentBinary) > 0 - - result[0].device = device - result[1].device = device - result[0].configuration = shaderConfiguration - result[1].configuration = shaderConfiguration - result[0].stage = VK_SHADER_STAGE_VERTEX_BIT - result[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT - - var createInfoVertex = VkShaderModuleCreateInfo( - sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - codeSize: uint(shaderConfiguration.vertexBinary.len * sizeof(uint32)), - pCode: addr(shaderConfiguration.vertexBinary[0]), - ) - checkVkResult vkCreateShaderModule(device.vk, addr(createInfoVertex), nil, addr(result[0].vk)) - var createInfoFragment = VkShaderModuleCreateInfo( - sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - codeSize: uint(shaderConfiguration.fragmentBinary.len * sizeof(uint32)), - pCode: addr(shaderConfiguration.fragmentBinary[0]), - ) - checkVkResult vkCreateShaderModule(device.vk, addr(createInfoFragment), nil, addr(result[1].vk)) - -proc getVertexInputInfo*( - shaderConfiguration: ShaderConfiguration, - bindings: var seq[VkVertexInputBindingDescription], - attributes: var seq[VkVertexInputAttributeDescription], - baseBinding=0'u32 -): VkPipelineVertexInputStateCreateInfo = - var location = 0'u32 - var binding = baseBinding - - for attribute in shaderConfiguration.inputs: - bindings.add VkVertexInputBindingDescription( - binding: binding, - stride: uint32(attribute.size), - inputRate: if attribute.perInstance: VK_VERTEX_INPUT_RATE_INSTANCE else: VK_VERTEX_INPUT_RATE_VERTEX, - ) - # allows to submit larger data structures like Mat44, for most other types will be 1 - for i in 0 ..< attribute.thetype.numberOfVertexInputAttributeDescriptors: - attributes.add VkVertexInputAttributeDescription( - binding: binding, - location: location, - format: attribute.thetype.getVkFormat, - offset: uint32(i * attribute.size(perDescriptor=true)), - ) - location += uint32(attribute.thetype.nLocationSlots) - inc binding - - return VkPipelineVertexInputStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - vertexBindingDescriptionCount: uint32(bindings.len), - pVertexBindingDescriptions: bindings.toCPointer, - vertexAttributeDescriptionCount: uint32(attributes.len), - pVertexAttributeDescriptions: attributes.toCPointer, - ) - - -proc getPipelineInfo*(shader: ShaderModule): VkPipelineShaderStageCreateInfo = - VkPipelineShaderStageCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - stage: shader.stage, - module: shader.vk, - pName: cstring(shader.configuration.entrypoint), - ) - -proc destroy*(shader: var ShaderModule) = - assert shader.device.vk.valid - assert shader.vk.valid - shader.device.vk.vkDestroyShaderModule(shader.vk, nil) - shader.vk.reset diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/swapchain.nim --- a/src/semicongine/vulkan/swapchain.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,231 +0,0 @@ -import std/options -import std/strformat -import std/logging - -import ../core -import ./device -import ./physicaldevice -import ./image -import ./framebuffer -import ./commandbuffer -import ./syncing - -type - Swapchain* = object - device*: Device - vk*: VkSwapchainKHR - dimension*: TVec2[uint32] - nImages*: uint32 - imageviews*: seq[ImageView] - framebuffers*: seq[Framebuffer] - currentInFlight*: int - currentFramebufferIndex: uint32 - framesRendered*: uint64 - queueFinishedFence*: seq[Fence] - imageAvailableSemaphore*: seq[Semaphore] - renderFinishedSemaphore*: seq[Semaphore] - commandBufferPool: CommandBufferPool - # required for recreation: - renderPass: VkRenderPass - surfaceFormat: VkSurfaceFormatKHR - queueFamily: QueueFamily - imageCount: uint32 - presentMode: VkPresentModeKHR - inFlightFrames*: int - - -proc createSwapchain*( - device: Device, - renderPass: VkRenderPass, - surfaceFormat: VkSurfaceFormatKHR, - queueFamily: QueueFamily, - desiredNumberOfImages=3'u32, - preferedPresentMode: VkPresentModeKHR=VK_PRESENT_MODE_MAILBOX_KHR, - inFlightFrames=2, - oldSwapchain=VkSwapchainKHR(0) -): Option[Swapchain] = - assert device.vk.valid - assert device.physicalDevice.vk.valid - assert renderPass.valid - assert inFlightFrames > 0 - - var capabilities = device.physicalDevice.getSurfaceCapabilities() - if capabilities.currentExtent.width == 0 or capabilities.currentExtent.height == 0: - return none(Swapchain) - - var imageCount = desiredNumberOfImages - - const PRESENTMODES_BY_PREFERENCE = [ - VK_PRESENT_MODE_MAILBOX_KHR, - VK_PRESENT_MODE_FIFO_RELAXED_KHR, - VK_PRESENT_MODE_FIFO_KHR, - VK_PRESENT_MODE_IMMEDIATE_KHR, - VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR, - VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, - ] - var supportedModes = device.physicalDevice.getSurfacePresentModes() - var presentMode: VkPresentModeKHR - for mode in PRESENTMODES_BY_PREFERENCE: - if mode in supportedModes: - presentMode = mode - break - - # following is according to vulkan specs - if presentMode in [VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR]: - imageCount = 1 - else: - imageCount = max(imageCount, capabilities.minImageCount) - if capabilities.maxImageCount != 0: - imageCount = min(imageCount, capabilities.maxImageCount) - var createInfo = VkSwapchainCreateInfoKHR( - sType: VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - surface: device.physicalDevice.surface, - minImageCount: imageCount, - imageFormat: surfaceFormat.format, - imageColorSpace: surfaceFormat.colorSpace, - imageExtent: capabilities.currentExtent, - imageArrayLayers: 1, - imageUsage: toBits [VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT], - # VK_SHARING_MODE_CONCURRENT no supported currently - imageSharingMode: VK_SHARING_MODE_EXCLUSIVE, - preTransform: capabilities.currentTransform, - compositeAlpha: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, # only used for blending with other windows, can be opaque - presentMode: presentMode, - clipped: true, - oldSwapchain: oldSwapchain, - ) - var - swapchain = Swapchain( - device: device, - surfaceFormat: surfaceFormat, - dimension: TVec2[uint32]([capabilities.currentExtent.width, capabilities.currentExtent.height]), - inFlightFrames: inFlightFrames, - queueFamily: queueFamily, - renderPass: renderPass - ) - - if device.vk.vkCreateSwapchainKHR(addr(createInfo), nil, addr(swapchain.vk)) == VK_SUCCESS: - var nImages: uint32 - checkVkResult device.vk.vkGetSwapchainImagesKHR(swapChain.vk, addr(nImages), nil) - swapchain.nImages = nImages - var images = newSeq[VkImage](nImages) - checkVkResult device.vk.vkGetSwapchainImagesKHR(swapChain.vk, addr(nImages), images.toCPointer) - for vkimage in images: - let image = VulkanImage(vk: vkimage, format: surfaceFormat.format, device: device) - let imageview = image.createImageView() - swapChain.imageviews.add imageview - swapChain.framebuffers.add swapchain.device.createFramebuffer(renderPass, [imageview], swapchain.dimension) - for i in 0 ..< swapchain.inFlightFrames: - swapchain.queueFinishedFence.add device.createFence() - swapchain.imageAvailableSemaphore.add device.createSemaphore() - swapchain.renderFinishedSemaphore.add device.createSemaphore() - swapchain.commandBufferPool = device.createCommandBufferPool(queueFamily, swapchain.inFlightFrames) - debug &"Created swapchain with: {nImages} framebuffers, {inFlightFrames} in-flight frames, {swapchain.dimension.x}x{swapchain.dimension.y}" - result = some(swapchain) - else: - result = none(Swapchain) - -proc currentFramebuffer*(swapchain: Swapchain): Framebuffer = - assert swapchain.device.vk.valid - assert swapchain.vk.valid - swapchain.framebuffers[swapchain.currentFramebufferIndex] - -proc nextFrame*(swapchain: var Swapchain): Option[VkCommandBuffer] = - assert swapchain.device.vk.valid - assert swapchain.vk.valid - - swapchain.currentInFlight = (swapchain.currentInFlight + 1) mod swapchain.inFlightFrames - swapchain.queueFinishedFence[swapchain.currentInFlight].wait() - - let nextImageResult = swapchain.device.vk.vkAcquireNextImageKHR( - swapchain.vk, - high(uint64), - swapchain.imageAvailableSemaphore[swapchain.currentInFlight].vk, - VkFence(0), - addr(swapchain.currentFramebufferIndex) - ) - - if nextImageResult == VK_SUCCESS: - swapchain.queueFinishedFence[swapchain.currentInFlight].reset() - result = some(swapchain.commandBufferPool.buffers[swapchain.currentInFlight]) - else: - result = none(VkCommandBuffer) - -proc swap*(swapchain: var Swapchain): bool = - assert swapchain.device.vk.valid - assert swapchain.vk.valid - assert swapchain.device.firstGraphicsQueue().isSome - assert swapchain.device.firstPresentationQueue().isSome - - var - commandBuffer = swapchain.commandBufferPool.buffers[swapchain.currentInFlight] - waitSemaphores = [swapchain.imageAvailableSemaphore[swapchain.currentInFlight].vk] - waitStages = [VkPipelineStageFlags(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)] - submitInfo = VkSubmitInfo( - sType: VK_STRUCTURE_TYPE_SUBMIT_INFO, - waitSemaphoreCount: 1, - pWaitSemaphores: addr(waitSemaphores[0]), - pWaitDstStageMask: addr(waitStages[0]), - commandBufferCount: 1, - pCommandBuffers: addr(commandBuffer), - signalSemaphoreCount: 1, - pSignalSemaphores: addr(swapchain.renderFinishedSemaphore[swapchain.currentInFlight].vk), - ) - checkVkResult vkQueueSubmit( - swapchain.device.firstGraphicsQueue().get.vk, - 1, - addr(submitInfo), - swapchain.queueFinishedFence[swapchain.currentInFlight].vk - ) - - var presentInfo = VkPresentInfoKHR( - sType: VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - waitSemaphoreCount: 1, - pWaitSemaphores: addr(swapchain.renderFinishedSemaphore[swapchain.currentInFlight].vk), - swapchainCount: 1, - pSwapchains: addr(swapchain.vk), - pImageIndices: addr(swapchain.currentFramebufferIndex), - pResults: nil, - ) - let presentResult = vkQueuePresentKHR(swapchain.device.firstPresentationQueue().get().vk, addr(presentInfo)) - if presentResult != VK_SUCCESS: - return false - - inc swapchain.framesRendered - return true - - -proc destroy*(swapchain: var Swapchain) = - assert swapchain.vk.valid - assert swapchain.commandBufferPool.vk.valid - - for imageview in swapchain.imageviews.mitems: - assert imageview.vk.valid - imageview.destroy() - for framebuffer in swapchain.framebuffers.mitems: - assert framebuffer.vk.valid - framebuffer.destroy() - swapchain.commandBufferPool.destroy() - for i in 0 ..< swapchain.inFlightFrames: - assert swapchain.queueFinishedFence[i].vk.valid - assert swapchain.imageAvailableSemaphore[i].vk.valid - assert swapchain.renderFinishedSemaphore[i].vk.valid - swapchain.queueFinishedFence[i].destroy() - swapchain.imageAvailableSemaphore[i].destroy() - swapchain.renderFinishedSemaphore[i].destroy() - - swapchain.device.vk.vkDestroySwapchainKHR(swapchain.vk, nil) - swapchain.vk.reset() - -proc recreate*(swapchain: var Swapchain): Option[Swapchain] = - assert swapchain.vk.valid - assert swapchain.device.vk.valid - result = createSwapchain( - device=swapchain.device, - renderPass=swapchain.renderPass, - surfaceFormat=swapchain.surfaceFormat, - queueFamily=swapchain.queueFamily, - desiredNumberOfImages=swapchain.imageCount, - inFlightFrames=swapchain.inFlightFrames, - oldSwapchain=swapchain.vk, - ) diff -r 611f9cee7495 -r 1c3e74f24db0 src/semicongine/vulkan/syncing.nim --- a/src/semicongine/vulkan/syncing.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -import ../core -import ./device - -type - Semaphore* = object - vk*: VkSemaphore - device: Device - Fence* = object - vk*: VkFence - device: Device - -proc createSemaphore*(device: Device): Semaphore = - assert device.vk.valid - var semaphoreInfo = VkSemaphoreCreateInfo(sType: VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO) - result.device = device - checkVkResult device.vk.vkCreateSemaphore(addr(semaphoreInfo), nil, addr(result.vk)) - -proc createFence*(device: Device): Fence = - assert device.vk.valid - var fenceInfo = VkFenceCreateInfo( - sType: VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - flags: toBits [VK_FENCE_CREATE_SIGNALED_BIT] - ) - result.device = device - checkVkResult device.vk.vkCreateFence(addr(fenceInfo), nil, addr(result.vk)) - -proc wait*(fence: Fence) = - assert fence.device.vk.valid - assert fence.vk.valid - var varFence = fence.vk - checkVkResult vkWaitForFences(fence.device.vk, 1, addr(varFence), false, high(uint64)) - -proc reset*(fence: Fence) = - assert fence.device.vk.valid - assert fence.vk.valid - var varFence = fence.vk - checkVkResult vkResetFences(fence.device.vk, 1, addr(varFence)) - -proc destroy*(semaphore: var Semaphore) = - assert semaphore.device.vk.valid - assert semaphore.vk.valid - semaphore.device.vk.vkDestroySemaphore(semaphore.vk, nil) - semaphore.vk.reset - -proc destroy*(fence: var Fence) = - assert fence.device.vk.valid - assert fence.vk.valid - fence.device.vk.vkDestroyFence(fence.vk, nil) - fence.vk.reset diff -r 611f9cee7495 -r 1c3e74f24db0 src/vulkan_api/config.nims --- a/src/vulkan_api/config.nims Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -import strformat - diff -r 611f9cee7495 -r 1c3e74f24db0 src/vulkan_api/vulkan_api_generator.nim --- a/src/vulkan_api/vulkan_api_generator.nim Mon Nov 27 23:14:09 2023 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,677 +0,0 @@ -import std/os -import std/sugar -import std/algorithm -import std/strformat -import std/strutils -import std/sequtils -import std/streams -import std/tables -import httpClient -import std/xmlparser -import std/xmltree - -const - TYPEMAP = { - "void": "void", - "char": "char", - "float": "float32", - "double": "float64", - "int8_t": "int8", - "uint8_t": "uint8", - "int16_t": "int16", - "uint16_t": "uint16", - "int32_t": "int32", - "uint32_t": "uint32", - "uint64_t": "uint64", - "int64_t": "int64", - "size_t": "csize_t", - "int": "cint", - "void*": "pointer", - "char*": "cstring", - "ptr char": "cstring", - "ptr void": "pointer", - "VK_DEFINE_HANDLE": "VkHandle", - "VK_DEFINE_NON_DISPATCHABLE_HANDLE": "VkNonDispatchableHandle", - }.toTable - PLATFORM_HEADER_MAP = { - "X11/Xlib.h": @["xlib", "xlib_xrandr"], - "X11/extensions/Xrandr.h": @["xlib_xrandr"], - "wayland-client.h": @["wayland"], - "windows.h": @["win32"], - "xcb/xcb.h": @["xcb"], - "directfb.h": @["directfb"], - "zircon/types.h": @["fuchsia"], - "ggp_c/vulkan_types.h": @["ggp"], - "screen/screen.h": @["screen"], - "nvscisync.h": @["sci"], - "nvscibuf.h": @["sci"], - "vk_video/vulkan_video_codec_h264std.h": @["provisional"], - "vk_video/vulkan_video_codec_h264std_decode.h": @["provisional"], - "vk_video/vulkan_video_codec_h264std_encode.h": @["provisional"], - "vk_video/vulkan_video_codec_h265std.h": @["provisional"], - "vk_video/vulkan_video_codec_h265std_decode.h": @["provisional"], - "vk_video/vulkan_video_codec_h265std_encode.h": @["provisional"], - }.toTable - MAP_KEYWORD = { - "object": "theobject", - "type": "thetype", - }.toTable - SPECIAL_DEPENDENCIES = { - "VK_NV_ray_tracing": "VK_KHR_ray_tracing_pipeline", - }.toTable - # will be directly loaded at startup - IGNORED_COMMANDS = @["vkGetInstanceProcAddr"] - # can be loaded without a vulkan instance - GLOBAL_COMMANDS = @[ - "vkEnumerateInstanceVersion", - "vkEnumerateInstanceExtensionProperties", - "vkEnumerateInstanceLayerProperties", - "vkCreateInstance", - ] - -# helpers -func mapType(typename: string): auto = - TYPEMAP.getOrDefault(typename.strip(), typename.strip()).strip(chars={'_'}) -func mapName(thename: string): auto = - MAP_KEYWORD.getOrDefault(thename.strip(), thename.strip()).strip(chars={'_'}) -func smartParseInt(value: string): int = - if value.startsWith("0x"): - parseHexInt(value) - else: - parseInt(value) -func hasAttr(node: XmlNode, attr: string): bool = node.attr(attr) != "" -func tableSorted(table: Table[int, string]): seq[(int, string)] = - result = toSeq(table.pairs) - result.sort((a, b) => cmp(a[0], b[0])) -func findType(declNode: XmlNode): string = - # examples: - # char** -> cstringArray - # void* -> pointer - # char* -> cstring - # - # int* -> ptr int - # void** -> ptr pointer - # int** -> ptr ptr int - var basetype = "" - var apointer = "" - var arraylen = "" - for child in declNode: - if child.kind == xnText: - if "[" in child.text: - if "[" in child.text and "]" in child.text: - arraylen = child.text.strip(chars={'[', ']'}).replace("][", "*") - else: - arraylen = declNode.child("enum")[0].text - else: - for i in 0 ..< child.text.count('*'): - apointer = apointer & "ptr " - elif child.tag == "type": - basetype = mapType(child[0].text) - if basetype == "void": - if apointer.count("ptr ") > 0: - basetype = "pointer" - apointer = apointer[0 ..< ^4] - elif basetype == "char": - if apointer.count("ptr ") == 1: - basetype = "cstring" - apointer = "" - elif apointer.count("ptr ") == 2: - basetype = "cstringArray" - apointer = "" - elif apointer.count("ptr ") > 2: - basetype = "cstringArray" - apointer = apointer[0 ..< ^8] - - result = &"{apointer}{basetype}" - if arraylen != "": - result = &"array[{arraylen}, {result}]" - -# serializers -# return values and whether this is a bitfield -func serializeEnum(node: XmlNode, api: XmlNode): (seq[string], string) = - let name = node.attr("name") - if name == "": - return result - - var reservedNames: seq[string] - for t in api.findAll("type"): - reservedNames.add t.attr("name").replace("_", "").toLower() - - # find additional enum defintion in feature definitions - var values: Table[int, string] - for feature in api.findAll("feature"): - for require in feature.findAll("require"): - for theenum in require.findAll("enum"): - if theenum.attr("extends") == name: - if theenum.hasAttr("offset"): - let enumBase = 1000000000 + (smartParseInt(theenum.attr("extnumber")) - 1) * 1000 - var value = smartParseInt(theenum.attr("offset")) + enumBase - if theenum.attr("dir") == "-": - value = -value - values[value] = theenum.attr("name") - elif theenum.hasAttr("value"): - var value = smartParseInt(theenum.attr("value")) - if theenum.attr("dir") == "-": - value = -value - values[value] = theenum.attr("name") - elif theenum.hasAttr("bitpos"): - var value = smartParseInt(theenum.attr("bitpos")) - if theenum.attr("dir") == "-": - value = -value - values[value] = theenum.attr("name") - elif theenum.hasAttr("alias"): - discard - else: - raise newException(Exception, &"Unknown extension value: {feature}\nvalue:{theenum}") - # find additional enum defintion in extension definitions - for extension in api.findAll("extension"): - let extensionNumber = parseInt(extension.attr("number")) - let enumBase = 1000000000 + (extensionNumber - 1) * 1000 - for require in extension.findAll("require"): - for theenum in require.findAll("enum"): - if theenum.attr("extends") == name: - if theenum.hasAttr("offset"): - if theenum.hasAttr("extnumber"): - let otherBase = 1000000000 + (smartParseInt(theenum.attr("extnumber")) - 1) * 1000 - var value = smartParseInt(theenum.attr("offset")) + otherBase - if theenum.attr("dir") == "-": - value = -value - values[value] = theenum.attr("name") - else: - var value = smartParseInt(theenum.attr("offset")) + enumBase - if theenum.attr("dir") == "-": - value = -value - values[value] = theenum.attr("name") - elif theenum.hasAttr("value"): - var value = smartParseInt(theenum.attr("value")) - if theenum.attr("dir") == "-": - value = -value - values[value] = theenum.attr("name") - elif theenum.hasAttr("bitpos"): - var value = smartParseInt(theenum.attr("bitpos")) - if theenum.attr("dir") == "-": - value = -value - values[value] = theenum.attr("name") - elif theenum.hasAttr("alias"): - discard - else: - raise newException(Exception, &"Unknown extension value: {extension}\nvalue:{theenum}") - - # generate enums - if node.attr("type") == "enum": - for value in node.findAll("enum"): - if value.hasAttr("alias"): - continue - if value.attr("value").startsWith("0x"): - values[parseHexInt(value.attr("value"))] = value.attr("name") - else: - values[smartParseInt(value.attr("value"))] = value.attr("name") - if values.len > 0: - result[0].add " " & name & "* {.size: sizeof(cint).} = enum" - for (value, name) in tableSorted(values): - var thename = name - if name.replace("_", "").toLower() in reservedNames: - thename = thename & "_ENUM" - let enumEntry = &" {thename} = {value}" - result[0].add enumEntry - - # generate bitsets (normal enums in the C API, but bitfield-enums in Nim) - elif node.attr("type") == "bitmask": - var predefined_enum_sets: seq[string] - for value in node.findAll("enum"): - if value.hasAttr("bitpos"): - values[smartParseInt(value.attr("bitpos"))] = value.attr("name") - elif node.attr("name") == "VkVideoEncodeRateControlModeFlagBitsKHR": # special exception, for some reason this has values instead of bitpos - values[smartParseInt(value.attr("value"))] = value.attr("name") - elif value.hasAttr("value"): # create a const that has multiple bits set - predefined_enum_sets.add &" {value.attr(\"name\")}* = {value.attr(\"value\")}" - - if values.len > 0: - let cApiName = name.replace("FlagBits", "Flags") - result[1] = cApiName - if node.hasAttr("bitwidth"): - result[0].add " " & name & "* {.size: 8.} = enum" - else: - result[0].add " " & name & "* {.size: sizeof(cint).} = enum" - for (bitpos, enumvalue) in tableSorted(values): - var value = "00000000000000000000000000000000"# makes the bit mask nicely visible - if node.hasAttr("bitwidth"): # assumes this is always 64 - value = value & value - value[^(bitpos + 1)] = '1' - let enumEntry = &" {enumvalue} = 0b{value}" - if not (enumEntry in result[0]): # the specs define duplicate entries for backwards compat - result[0].add enumEntry - if node.hasAttr("bitwidth"): # assuming this attribute is always 64 - if values.len > 0: - result[0].add &"""func toBits*(flags: openArray[{name}]): {cApiName} = - for flag in flags: - result = {cApiName}(uint64(result) or uint64(flag))""" - result[0].add &"""func toEnums*(number: {cApiName}): seq[{name}] = - for value in {name}.items: - if (cast[uint64](value) and uint64(number)) > 0: - result.add value""" - result[0].add &"proc `==`*(a, b: {cApiName}): bool = uint64(a) == uint64(b)" - else: - if values.len > 0: - result[0].add &"""func toBits*(flags: openArray[{name}]): {cApiName} = - for flag in flags: - result = {cApiName}(uint(result) or uint(flag))""" - result[0].add &"""func toEnums*(number: {cApiName}): seq[{name}] = - for value in {name}.items: - if (value.ord and cint(number)) > 0: - result.add value""" - result[0].add &"proc `==`*(a, b: {cApiName}): bool = cint(a) == cint(b)" - if predefined_enum_sets.len > 0: - result[0].add "const" - result[0].add predefined_enum_sets - result[0].add "type" - - -func serializeStruct(node: XmlNode): seq[string] = - let name = node.attr("name") - var union = "" - if node.attr("category") == "union": - union = "{.union.} " - result.add &" {name}* {union}= object" - for member in node.findAll("member"): - if not member.hasAttr("api") or member.attr("api") == "vulkan": - let fieldname = member.child("name")[0].text.strip(chars={'_'}) - result.add &" {mapName(fieldname)}*: {findType(member)}" - -func serializeFunctiontypes(api: XmlNode): seq[string] = - for node in api.findAll("type"): - if node.attr("category") == "funcpointer": - let name = node[1][0] - let returntype = mapType(node[0].text[8 .. ^1].split('(', 1)[0]) - var params: seq[string] - for i in countup(3, node.len - 1, 2): - var paramname = node[i + 1].text.split(',', 1)[0].split(')', 1)[0] - var paramtype = node[i][0].text - if paramname[0] == '*': - paramname = paramname.rsplit(" ", 1)[1] - paramtype = "ptr " & paramtype - paramname = mapName(paramname) - params.add &"{paramname}: {mapType(paramtype)}" - let paramsstr = params.join(", ") - result.add(&" {name}* = proc({paramsstr}): {returntype} {{.cdecl.}}") - -func serializeConsts(api: XmlNode): seq[string] = - result = @["const"] - for enums in api.findAll("enums"): - if enums.attr("name") == "API Constants": - for theenum in enums.findAll("enum"): - if theenum.hasAttr("alias"): - result.add &" {theenum.attr(\"name\")}* = {theenum.attr(\"alias\")}" - else: - var value = theenum.attr("value").strip(chars={'(', ')'}) - if value.endsWith("U"): - value = value[0..^2] & "'u32" - elif value.endsWith("ULL"): - value = value[0..^4] & "'u64" - if value[0] == '~': - value = "not " & value[1..^1] - result.add &" {theenum.attr(\"name\")}*: {mapType(theenum.attr(\"type\"))} = {value}" - -func serializeType(node: XmlNode, headerTypes: Table[string, string]): Table[string, seq[string]] = - if node.attrsLen == 0: - return - if node.attr("requires") == "vk_platform" or node.attr("category") == "include": - return - result["basetypes"] = @[] - result["enums"] = @[] - - # include-defined types (in platform headers) - if node.attr("name") in headerTypes: - for platform in PLATFORM_HEADER_MAP[node.attr("requires")]: - let platformfile = "platform/" & platform - if not result.hasKey(platformfile): - result[platformfile] = @[] - result[platformfile].add " " & node.attr("name").strip(chars={'_'}) & " *{.header: \"" & node.attr("requires") & "\".} = object" - # generic base types - elif node.attr("category") == "basetype": - let typechild = node.child("type") - let namechild = node.child("name") - if typechild != nil and namechild != nil: - var typename = typechild[0].text - if node[2].kind == xnText and node[2].text.strip() == "*": - typename = &"ptr {typename}" - result["basetypes"].add &" {namechild[0].text}* = {mapType(typename)}" - elif namechild != nil: - result["basetypes"].add &" {namechild[0].text}* = object" - # function pointers need to be handled with structs - elif node.attr("category") == "funcpointer": - discard - # preprocessor defines, ignored - elif node.attr("category") == "define": - discard - # bitmask aliases - elif node.attr("category") == "bitmask": - if node.hasAttr("alias"): - let name = node.attr("name") - let alias = node.attr("alias") - result["enums"].add &" {name}* = {alias}" - # distinct resource ID types aka handles - elif node.attr("category") == "handle": - if not node.hasAttr("alias"): - let name = node.child("name")[0].text - var thetype = mapType(node.child("type")[0].text) - result["basetypes"].add &" {name}* = distinct {thetype}" - # enum aliases - elif node.attr("category") == "enum": - if node.hasAttr("alias"): - let name = node.attr("name") - let alias = node.attr("alias") - result["enums"].add &" {name}* = {alias}" - else: - discard - -func serializeCommand(node: XmlNode): (string, string) = - let - proto = node.child("proto") - resulttype = mapType(proto.child("type")[0].text) - name = proto.child("name")[0].text - var params: seq[string] - for param in node: - if param.tag == "param" and param.attr("api") in ["", "vulkan"]: - let fieldname = param.child("name")[0].text.strip(chars={'_'}) - params.add &"{mapName(fieldname)}: {findType(param)}" - let allparams = params.join(", ") - return (name, &"proc({allparams}): {resulttype} {{.stdcall.}}") - - -proc update(a: var Table[string, seq[string]], b: Table[string, seq[string]]) = - for k, v in b.pairs: - if not a.hasKey(k): - a[k] = @[] - a[k].add v - - -proc main() = - let file = getTempDir() / "vk.xml" - if not os.fileExists(file): - let client = newHttpClient() - let glUrl = "https://raw.githubusercontent.com/KhronosGroup/Vulkan-Docs/main/xml/vk.xml" - client.downloadFile(glUrl, file) - - let api = loadXml(file) - - const outdir = "src/vulkan_api/output" - removeDir outdir - createDir outdir - createDir outdir / "platform" - - # index all names that are only available on certain platforms - var platformTypes: Table[string, string] - for extension in api.findAll("extension"): - if extension.hasAttr("platform"): - for thetype in extension.findAll("type"): - platformTypes[thetype.attr("name")] = extension.attr("platform") - for command in extension.findAll("command"): - platformTypes[command.attr("name")] = extension.attr("platform") - elif extension.attr("name").startsWith("VK_KHR_video"): - for thetype in extension.findAll("type"): - platformTypes[thetype.attr("name")] = "provisional" - for command in extension.findAll("command"): - platformTypes[command.attr("name")] = "provisional" - - var outputFiles = { - "basetypes": @[ - "import std/dynlib", - "import std/tables", - "import std/strutils", - "import std/logging", - "import std/typetraits", - "import std/macros", - "type", - " VkHandle* = distinct uint", - " VkNonDispatchableHandle* = distinct uint", - "when defined(linux):", - " let vulkanLib* = loadLib(\"libvulkan.so.1\")", - "when defined(windows):", - " let vulkanLib* = loadLib(\"vulkan-1.dll\")", - "if vulkanLib == nil:", - " raise newException(Exception, \"Unable to load vulkan library\")", - "func VK_MAKE_API_VERSION*(variant: uint32, major: uint32, minor: uint32, patch: uint32): uint32 {.compileTime.} =", - " (variant shl 29) or (major shl 22) or (minor shl 12) or patch", - "", - """template checkVkResult*(call: untyped) = - when defined(release): - discard call - else: - # yes, a bit cheap, but this is only for nice debug output - var callstr = astToStr(call).replace("\n", "") - while callstr.find(" ") >= 0: - callstr = callstr.replace(" ", " ") - debug "CALLING vulkan: ", callstr - let value = call - if value != VK_SUCCESS: - error "Vulkan error: ", astToStr(call), " returned ", $value - raise newException(Exception, "Vulkan error: " & astToStr(call) & - " returned " & $value)""", - """ -# custom enum iteration (for enum values > 2^16) -macro enumFullRange(a: typed): untyped = - newNimNode(nnkBracket).add(a.getType[1][1..^1]) - -iterator items*[T: HoleyEnum](E: typedesc[T]): T = - for a in enumFullRange(E): yield a""", - ], - "structs": @["type"], - "enums": @["type"], - "commands": @[], - }.toTable - outputFiles["basetypes"].add serializeConsts(api) - outputFiles["basetypes"].add "type" - - # enums - for thetype in api.findAll("type"): - if thetype.attr("category") == "bitmask" and not thetype.hasAttr("alias") and (not thetype.hasAttr("api") or thetype.attr("api") == "vulkan"): - let name = thetype.child("name")[0].text - outputFiles["enums"].add &" {name}* = distinct VkFlags" - - var bitfields: Table[string, string] - outputFiles["enums"].add "let vkGetInstanceProcAddr = cast[proc(instance: VkInstance, name: cstring): pointer {.stdcall.}](checkedSymAddr(vulkanLib, \"vkGetInstanceProcAddr\"))" - outputFiles["enums"].add "type" - for theenum in api.findAll("enums"): - let (enums, bitFieldName) = serializeEnum(theenum, api) - outputFiles["enums"].add enums - if bitFieldName != "": - bitfields[theenum.attr("name")] = bitFieldName - - # bitmask-to-string functions - for thetype in api.findAll("type"): - if thetype.attr("name") in bitfields: - let name = bitfields[thetype.attr("name")] - let stringfunc = &"proc `$`*(bitset: {name}): string = $toEnums(bitset)" - if not (stringfunc in outputFiles["enums"]): - outputFiles["enums"].add stringfunc - outputFiles["enums"].add "type" - - # structs and function types need to be in same "type" block to avoid forward-declarations - outputFiles["structs"].add serializeFunctiontypes(api) - for thetype in api.findAll("type"): - if thetype.attr("category") == "struct" or thetype.attr("category") == "union": - var outfile = "structs" - if thetype.attr("name") in platformTypes: - outfile = "platform/" & platformTypes[thetype.attr("name")] - if not (outfile in outputFiles): - outputFiles[outfile] = @[] - outputFiles[outfile].add serializeStruct(thetype) - - # types - var headerTypes: Table[string, string] - for types in api.findAll("types"): - for thetype in types.findAll("type"): - if thetype.attrsLen == 2 and thetype.hasAttr("requires") and thetype.hasAttr("name") and thetype.attr("requires") != "vk_platform": - let name = thetype.attr("name") - let incld = thetype.attr("requires") - headerTypes[name] = &"{name} {{.header: \"{incld}\".}} = object" - - for typesgroup in api.findAll("types"): - for thetype in typesgroup.findAll("type"): - outputFiles.update serializeType(thetype, headerTypes) - - for typesgroup in api.findAll("types"): - for node in typesgroup.findAll("type"): - if node.attr("category") == "handle": - if not node.hasAttr("alias"): - let name = node.child("name")[0].text - outputFiles["basetypes"].add &"proc `$`*(handle: {name}): string = \"{name}(\" & $(uint(handle)) & \")\"" - outputFiles["basetypes"].add &"proc valid*(handle: {name}): bool = uint(handle) != 0" - outputFiles["basetypes"].add &"proc reset*(handle: var {name}) = handle = {name}(0)" - outputFiles["basetypes"].add &"proc `==`*(a, b: {name}): bool = uint(a) == uint(b)" - - - # commands aka functions - var varDecls: Table[string, string] - var procLoads: Table[string, string] # procloads need to be packed into feature/extension loader procs - for commands in api.findAll("commands"): - for command in commands.findAll("command"): - if command.attr("api") != "vulkansc" and not (command.attr("name") in IGNORED_COMMANDS): - if command.hasAttr("alias"): - let name = command.attr("name") - let alias = command.attr("alias") - let thetype = varDecls[alias].split(":", 1)[1].strip() - varDecls[name] = &" {name}*: {thetype}" - procLoads[name] = &" {name} = {alias}" - else: - let (name, thetype) = serializeCommand(command) - varDecls[name] = &" {name}*: {thetype}" - procLoads[name] = &" {name} = cast[{thetype}](vkGetInstanceProcAddr(instance, \"{name}\"))" - var declared: seq[string] - var featureloads: seq[string] - for feature in api.findAll("feature"): - if feature.attr("api") in ["vulkan", "vulkan,vulkansc"]: - let name = feature.attr("name") - outputFiles["commands"].add &"# feature {name}" - outputFiles["commands"].add "var" - for command in feature.findAll("command"): - if not (command.attr("name") in declared) and not (command.attr("name") in IGNORED_COMMANDS): - outputFiles["commands"].add varDecls[command.attr("name")] - declared.add command.attr("name") - featureloads.add &"load{name}" - outputFiles["commands"].add &"proc load{name}*(instance: VkInstance) =" - for command in feature.findAll("command"): - if not (command.attr("name") in IGNORED_COMMANDS & GLOBAL_COMMANDS): - outputFiles["commands"].add procLoads[command.attr("name")] - outputFiles["commands"].add "" - outputFiles["commands"].add ["proc loadVulkan*(instance: VkInstance) ="] - for l in featureloads: - outputFiles["commands"].add [&" {l}(instance)"] - outputFiles["commands"].add "" - - # for promoted extensions, dependants need to call the load-function of the promoted feature/extension - # use table to store promotions - var promotions: Table[string, string] - for extensions in api.findAll("extensions"): - for extension in extensions.findAll("extension"): - if extension.hasAttr("promotedto"): - promotions[extension.attr("name")] = extension.attr("promotedto") - - var extensionDependencies: Table[string, (seq[string], XmlNode)] - var features: seq[string] - for feature in api.findAll("feature"): - features.add feature.attr("name") - for extensions in api.findAll("extensions"): - for extension in extensions.findAll("extension"): - let name = extension.attr("name") - extensionDependencies[name] = (@[], extension) - if extension.hasAttr("depends"): - extensionDependencies[name] = (extension.attr("depends").split("+"), extension) - if extension.attr("depends").startsWith("("): # no need for full tree parser, only single place where we can use a feature - let dependencies = extension.attr("depends").rsplit({')'}, 1)[1][1 .. ^1].split("+") - extensionDependencies[name] = (dependencies, extension) - if name in SPECIAL_DEPENDENCIES: - extensionDependencies[name][0].add SPECIAL_DEPENDENCIES[name] - - # order dependencies to generate them in correct order - var dependencyOrderedExtensions: OrderedTable[string, XmlNode] - while extensionDependencies.len > 0: - var delkeys: seq[string] - for extensionName, (dependencies, extension) in extensionDependencies.pairs: - var missingExtension = false - for dep in dependencies: - let realdep = promotions.getOrDefault(dep, dep) - if not (realdep in dependencyOrderedExtensions) and not (realdep in features): - missingExtension = true - break - if not missingExtension: - dependencyOrderedExtensions[extensionName] = extension - delkeys.add extensionName - for key in delkeys: - extensionDependencies.del key - - var extensionLoaderMap: Table[string, Table[string, string]] - for extension in dependencyOrderedExtensions.values: - if extension.hasAttr("promotedto"): # will be loaded in promoted place - continue - if extension.attr("supported") in ["", "vulkan", "vulkan,vulkansc"]: - var file = "commands" - var platform = extension.attr("platform") - if extension.attr("name").startsWith("VK_KHR_video"): - platform = "provisional" - if platform != "": - file = "platform/" & platform - let name = extension.attr("name") - if extension.findAll("command").len > 0: - outputFiles[file].add &"# extension {name}" - outputFiles[file].add "var" - for command in extension.findAll("command"): - if not (command.attr("name") in declared) and not (command.attr("name") in IGNORED_COMMANDS): - outputFiles[file].add varDecls[command.attr("name")] - declared.add command.attr("name") - outputFiles[file].add &"proc load{name}*(instance: VkInstance) =" - if not (platform in extensionLoaderMap): - extensionLoaderMap[platform] = Table[string, string]() - extensionLoaderMap[platform][name] = &"load{name}" - var addedFunctionBody = false - if extension.hasAttr("depends"): - for dependency in extension.attr("depends").split("+"): - # need to check since some extensions have no commands and therefore no load-function - outputFiles[file].add &" load{promotions.getOrDefault(dependency, dependency)}(instance)" - addedFunctionBody = true - for command in extension.findAll("command"): - outputFiles[file].add procLoads[command.attr("name")] - addedFunctionBody = true - if not addedFunctionBody: - outputFiles[file].add " discard" - outputFiles[file].add "" - - var mainout: seq[string] - for section in ["basetypes", "enums", "structs", "commands"]: - mainout.add outputFiles[section] - mainout.add "var EXTENSION_LOADERS = {" - for extension, loader in extensionLoaderMap[""].pairs: - mainout.add &" \"{extension}\": {loader}," - mainout.add "}.toTable" - for platform in api.findAll("platform"): - mainout.add &"when defined({platform.attr(\"protect\")}):" - mainout.add &" ../vulkan/include platform/{platform.attr(\"name\")}" - if platform.attr("name") in extensionLoaderMap: - for extension, loader in extensionLoaderMap[platform.attr("name")].pairs: - mainout.add &" EXTENSION_LOADERS[\"{extension}\"] = {loader}" - - mainout.add "" - mainout.add "proc loadExtension*(instance: VkInstance, extension: string) = EXTENSION_LOADERS[extension](instance)" - mainout.add "" - mainout.add "# load global functions immediately" - mainout.add "block globalFunctions:" - mainout.add " let instance = VkInstance(0)" - for l in GLOBAL_COMMANDS: - mainout.add procLoads[l] - mainout.add "" - # produces error if enable both implicit converters - # mainout.add "converter VkBool2NimBool*(a: VkBool32): bool = a > 0" - mainout.add "converter NimBool2VkBool*(a: bool): VkBool32 = VkBool32(a)" - - writeFile outdir / &"api.nim", mainout.join("\n") - - - for filename, filecontent in outputFiles.pairs: - if filename.startsWith("platform/"): - writeFile outdir / &"{filename}.nim", (@[ - "type" - ] & filecontent).join("\n") - -when isMainModule: - main()